Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Login to Github before entering repository name #169

Merged
merged 26 commits into from
Sep 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
fdbca46
Add minimal login component
chia-yh Jul 11, 2023
03137a3
Change auth process to login before selecting repo
chia-yh Jul 12, 2023
febec0a
Add login component tests and edit existing tests
chia-yh Jul 12, 2023
92c822e
Add newline at eof
chia-yh Jul 12, 2023
bb4833f
Reset sessionSetupState
chia-yh Jul 12, 2023
65ed192
Merge branch 'main' into login-before-select-session
chia-yh Jul 12, 2023
6ff76b1
Fix tests
chia-yh Jul 12, 2023
cac106c
Address review comments
chia-yh Jul 16, 2023
fc950a9
Merge branch 'main' into login-before-select-session
chia-yh Jul 16, 2023
62eff89
Modify to alternative implementation
chia-yh Jul 17, 2023
39b064f
Modify tests
chia-yh Jul 17, 2023
ae59d29
Remove unnecessary condition
chia-yh Jul 17, 2023
d88b166
Add condition to display change repository button
chia-yh Jul 17, 2023
6f31bd5
Add condition to display repository buttons
chia-yh Jul 17, 2023
0638147
Resolve merge conflicts
chia-yh Jul 18, 2023
e2b0658
Fix lint error
chia-yh Jul 18, 2023
8097fe7
Merge branch 'main' into login-before-select-session
chia-yh Jul 24, 2023
f9c6ad2
Rename, move methods concerning repo setup
chia-yh Jul 27, 2023
d1a2e66
Modify isRepoSet
chia-yh Jul 27, 2023
e9d31ed
Fix session-selection-component appearing
chia-yh Jul 27, 2023
5d8756c
Shift isValidRepository check into phase service
chia-yh Jul 29, 2023
26522ec
Fix lint errors
chia-yh Jul 29, 2023
648b4a2
Remove unused onInit implementation
chia-yh Jul 29, 2023
1ea21a3
Merge branch 'main' into login-before-select-session
chia-yh Aug 8, 2023
24f3dd8
Merge branch 'main' into login-before-select-session
chia-yh Aug 16, 2023
3b3e6fb
Revert removal of label service
chia-yh Aug 17, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,9 @@ import { SharedModule } from './shared/shared.module';
PhaseService,
GithubEventService,
Title,
LoggingService]
ErrorHandlingService,
LoggingService
]
},
{
provide: IssueService,
Expand Down
14 changes: 11 additions & 3 deletions src/app/auth/auth.component.html
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
<div *ngIf="isUserNotAuthenticated()" class="login-page">
<app-session-selection [urlEncodedSessionName]="this.urlEncodedSessionName" [urlEncodedRepo]="this.urlEncodedRepo">
</app-session-selection>
<mat-card class="login-card">
<mat-card-header style="margin-bottom: 20px">
<mat-card-title class="login-title"> WATcher </mat-card-title>
</mat-card-header>
<app-auth-login></app-auth-login>
</mat-card>
</div>

<div *ngIf="isUserAuthenticating() || isAwaitingOAuthUserConfirm()" class="login-page">
<mat-card class="login-card">
<mat-card-header style="margin-bottom: 20px">
<mat-card-title class="login-title"> Confirm Login Account </mat-card-title>
<mat-card-subtitle> Session on {{ currentSessionOrg }} </mat-card-subtitle>
</mat-card-header>

<div style="position: absolute; top: 15px; left: 15px">
Expand All @@ -24,3 +27,8 @@
</div>
</mat-card>
</div>

<div *ngIf="isUserAuthenticated() && !isRepoSet()" class="login-page">
<app-session-selection [urlEncodedSessionName]="this.urlEncodedSessionName" [urlEncodedRepo]="this.urlEncodedRepo">
</app-session-selection>
</div>
8 changes: 8 additions & 0 deletions src/app/auth/auth.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,14 @@ export class AuthComponent implements OnInit, OnDestroy {
return this.authState === AuthState.ConfirmOAuthUser;
}

Eclipse-Dominator marked this conversation as resolved.
Show resolved Hide resolved
isUserAuthenticated(): boolean {
return this.authState === AuthState.Authenticated;
}

isRepoSet(): boolean {
return this.phaseService.isRepoSet();
}

get currentSessionOrg(): string {
if (!this.sessionInformation) {
// Retrieve org details of session information from local storage
Expand Down
10 changes: 9 additions & 1 deletion src/app/auth/auth.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,20 @@ import { SharedModule } from '../shared/shared.module';
import { AuthRoutingModule } from './auth-routing.module';
import { AuthComponent } from './auth.component';
import { ConfirmLoginComponent } from './confirm-login/confirm-login.component';
import { LoginComponent } from './login/login.component';
import { JsonParseErrorDialogComponent } from './profiles/json-parse-error-dialog/json-parse-error-dialog.component';
import { ProfilesComponent } from './profiles/profiles.component';
import { SessionSelectionComponent } from './session-selection/session-selection.component';

@NgModule({
imports: [AuthRoutingModule, SharedModule, CommonModule],
declarations: [AuthComponent, ProfilesComponent, JsonParseErrorDialogComponent, ConfirmLoginComponent, SessionSelectionComponent]
declarations: [
AuthComponent,
ProfilesComponent,
JsonParseErrorDialogComponent,
LoginComponent,
ConfirmLoginComponent,
SessionSelectionComponent
]
})
export class AuthModule {}
42 changes: 2 additions & 40 deletions src/app/auth/confirm-login/confirm-login.component.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,7 @@
import { Component, Input, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { Observable, of } from 'rxjs';
import { mergeMap } from 'rxjs/operators';
import { Phase } from '../../core/models/phase.model';
import { Repo } from '../../core/models/repo.model';
import { AuthService, AuthState } from '../../core/services/auth.service';
import { ErrorHandlingService } from '../../core/services/error-handling.service';
import { GithubService } from '../../core/services/github.service';
import { GithubEventService } from '../../core/services/githubevent.service';
import { LoggingService } from '../../core/services/logging.service';
import { PhaseService } from '../../core/services/phase.service';
import { UserService } from '../../core/services/user.service';

@Component({
Expand All @@ -23,13 +15,9 @@ export class ConfirmLoginComponent implements OnInit {

constructor(
private authService: AuthService,
private phaseService: PhaseService,
private userService: UserService,
private errorHandlingService: ErrorHandlingService,
private githubEventService: GithubEventService,
private logger: LoggingService,
private router: Router,
public githubService: GithubService
) {}

ngOnInit() {}
Expand All @@ -44,49 +32,23 @@ export class ConfirmLoginComponent implements OnInit {
this.authService.startOAuthProcess();
}

/**
* Handles the clean up required after authentication and setting up of user data is completed.
*/
handleAuthSuccess() {
this.authService.setTitleWithPhaseDetail();
this.router.navigateByUrl(Phase.issuesViewer);
this.authService.changeAuthState(AuthState.Authenticated);
}

/**
* Will complete the process of logging in the given user.
*/
completeLoginProcess(): void {
this.authService.changeAuthState(AuthState.AwaitingAuthentication);
this.phaseService.initializeCurrentRepository();
this.logger.info(`ConfirmLoginComponent: Current repo is ${this.phaseService.currentRepo}`);
this.logger.info(`ConfirmLoginComponent: Completing login process`);
this.userService
gycgabriel marked this conversation as resolved.
Show resolved Hide resolved
.createUserModel(this.username)
.pipe(
mergeMap(() => {
const currentRepo = this.phaseService.currentRepo;
if (Repo.isInvalidRepoName(currentRepo)) {
return of(false);
}
return this.githubService.isRepositoryPresent(currentRepo.owner, currentRepo.name);
}),
mergeMap((isValidRepository) => {
if (!isValidRepository) {
return new Observable();
}
return this.githubEventService.setLatestChangeEvent();
})
)
.subscribe(
() => {
this.handleAuthSuccess();
this.authService.changeAuthState(AuthState.Authenticated);
},
(error) => {
this.authService.changeAuthState(AuthState.NotAuthenticated);
this.errorHandlingService.handleError(error);
this.logger.info(`ConfirmLoginComponent: Completion of login process failed with an error: ${error}`);
}
);
this.handleAuthSuccess();
}
}
18 changes: 18 additions & 0 deletions src/app/auth/login/login.component.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
.login-button {
background: #f7fcfe;
line-height: 45px;
border: 1px solid currentColor;
width: 100%;
}

.logo {
align-items: center;
display: inline-flex;
margin: 0 3px 3px 3px;
}

.github-logo {
font-size: 20px;
width: 20px;
height: 20px;
}
4 changes: 4 additions & 0 deletions src/app/auth/login/login.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<button mat-stroked-button class="login-button" color="primary" (click)="startLoginProcess()">
<span class="logo"> <img class="github-logo" src="./assets/images/github-logo.png" alt="github-logo" /> </span>
<span> Login </span>
</button>
29 changes: 29 additions & 0 deletions src/app/auth/login/login.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { Component } from '@angular/core';
import { AuthService, AuthState } from '../../core/services/auth.service';
import { ErrorHandlingService } from '../../core/services/error-handling.service';
import { LoggingService } from '../../core/services/logging.service';

@Component({
selector: 'app-auth-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})

export class LoginComponent {
constructor(
private authService: AuthService,
private errorHandlingService: ErrorHandlingService,
private logger: LoggingService
) {}

startLoginProcess() {
this.logger.info('LoginComponent: Beginning login process');
try {
this.authService.startOAuthProcess();
} catch (error) {
this.authService.changeAuthState(AuthState.NotAuthenticated);
this.errorHandlingService.handleError(error);
this.logger.info(`LoginComponent: Login process failed with an error: ${error}`);
}
gycgabriel marked this conversation as resolved.
Show resolved Hide resolved
}
}
15 changes: 7 additions & 8 deletions src/app/auth/session-selection/session-selection.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { Observable } from 'rxjs';
import { Profile } from '../../core/models/profile.model';
import { AuthService, AuthState } from '../../core/services/auth.service';
import { AuthService } from '../../core/services/auth.service';
import { ErrorHandlingService } from '../../core/services/error-handling.service';
import { LoggingService } from '../../core/services/logging.service';
import { RepoUrlCacheService } from '../../core/services/repo-url-cache.service';
Expand Down Expand Up @@ -78,13 +78,12 @@ export class SessionSelectionComponent implements OnInit {

this.logger.info(`SessionSelectionComponent: Selected Repository: ${repoInformation}`);

try {
this.authService.startOAuthProcess();
} catch (error) {
this.errorHandlingService.handleError(error);
this.authService.changeAuthState(AuthState.NotAuthenticated);
this.isSettingUpSession = false;
gycgabriel marked this conversation as resolved.
Show resolved Hide resolved
}
this.authService.setRepo()
.subscribe(
(res) => {
this.isSettingUpSession = false;
}
);
}

/**
Expand Down
37 changes: 35 additions & 2 deletions src/app/core/services/auth.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@ import { Injectable } from '@angular/core';
import { NgZone } from '@angular/core';
import { Title } from '@angular/platform-browser';
import { Router } from '@angular/router';
import { BehaviorSubject } from 'rxjs';
import { BehaviorSubject, from, Observable, of } from 'rxjs';
import { catchError, map } from 'rxjs/operators';
import { AppConfig } from '../../../environments/environment';
import { generateSessionId } from '../../shared/lib/session';
import { uuid } from '../../shared/lib/uuid';
import { Phase } from '../models/phase.model';
import { ErrorHandlingService } from './error-handling.service';
import { GithubService } from './github.service';
import { GithubEventService } from './githubevent.service';
import { IssueService } from './issue.service';
Expand Down Expand Up @@ -47,8 +50,9 @@ export class AuthService {
private phaseService: PhaseService,
private githubEventService: GithubEventService,
private titleService: Title,
private errorHandlingService: ErrorHandlingService,
private logger: LoggingService
) {}
) {}

/**
* Will store the OAuth token.
Expand Down Expand Up @@ -136,6 +140,35 @@ export class AuthService {
this.logger.info(`AuthService: Redirecting for Github authentication`);
}

/**
* Handles the clean up required after authentication and setting up of repository is completed.
*/
handleSetRepoSuccess() {
this.setTitleWithPhaseDetail();
this.router.navigateByUrl(Phase.issuesViewer);
}

/**
* Setup repository after authentication.
*/
setRepo(): Observable<boolean> {
return from(this.phaseService.initializeCurrentRepository())
.pipe(
map(() => {
if (!this.phaseService.currentRepo) {
return false;
}
this.githubEventService.setLatestChangeEvent();
this.handleSetRepoSuccess();
return true;
}),
catchError((error) => {
this.errorHandlingService.handleError(error);
return of(false);
})
);
}

/**
* Will redirect to GitHub OAuth page
*/
Expand Down
6 changes: 5 additions & 1 deletion src/app/core/services/factories/factory.auth.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Title } from '@angular/platform-browser';
import { Router } from '@angular/router';
// import { AppConfig } from '../../../../environments/environment';
import { AuthService } from '../auth.service';
import { ErrorHandlingService } from '../error-handling.service';
import { GithubService } from '../github.service';
import { GithubEventService } from '../githubevent.service';
import { IssueService } from '../issue.service';
Expand All @@ -22,6 +23,7 @@ export function AuthServiceFactory(
phaseService: PhaseService,
githubEventService: GithubEventService,
titleService: Title,
errorHandlingService: ErrorHandlingService,
logger: LoggingService
) {
// TODO: Write Mocks
Expand Down Expand Up @@ -50,5 +52,7 @@ export function AuthServiceFactory(
phaseService,
githubEventService,
titleService,
logger);
errorHandlingService,
logger
);
}
19 changes: 17 additions & 2 deletions src/app/core/services/phase.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ export class PhaseService {
public currentRepo: Repo; // current or main repository of current phase
public otherRepos: Repo[]; // more repositories relevant to this phase

repoSetSource = new BehaviorSubject(false);
repoSetState = this.repoSetSource.asObservable();

/**
* Expose an observable to track changes to currentRepo
*
Expand All @@ -58,7 +61,10 @@ export class PhaseService {

public sessionData = STARTING_SESSION_DATA; // stores session data for the session

constructor(private githubService: GithubService, private repoUrlCacheService: RepoUrlCacheService, public logger: LoggingService) {}
constructor(
private githubService: GithubService,
private repoUrlCacheService: RepoUrlCacheService,
public logger: LoggingService) {}

/**
* Sets the current main repository and additional repos if any.
Expand Down Expand Up @@ -120,7 +126,7 @@ export class PhaseService {
/**
* Retrieves the repository url from local storage and sets to current repository.
*/
initializeCurrentRepository() {
async initializeCurrentRepository() {
const org = window.localStorage.getItem('org');
const repoName = window.localStorage.getItem('dataRepo');
this.logger.info(`Phase Service: received initial org (${org}) and initial name (${repoName})`);
Expand All @@ -130,8 +136,17 @@ export class PhaseService {
} else {
repo = new Repo(org, repoName);
}
const isValidRepository = await this.githubService.isRepositoryPresent(repo.owner, repo.name).toPromise();
if (!isValidRepository) {
throw new Error('Invalid repository name. Please check your organisation and repository name.');
}
this.logger.info(`PhaseService: Repo is ${repo}`);
this.setRepository(repo);
this.repoSetSource.next(true);
}

isRepoSet(): boolean {
return this.repoSetSource.getValue();
}

/**
Expand Down
Loading