Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
Next Next commit
add auth app
  • Loading branch information
Nicole Garcia committed Nov 8, 2022
commit 88e6cb77c13182d6f496ef21a697e5ea6a02c1cc
2 changes: 2 additions & 0 deletions .github/workflows/CD-time-tracker-ui.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ jobs:
SCOPES: ${{ secrets.scopes }}
CLIENT_ID: ${{ secrets.client_id }}
CLIENT_URL: ${{ secrets.client_url }}
AUTH_URL: ${{ secrets.AUTH_URL }}
AUTH_APP_NAME: ${{ secrets.AUTH_APP_NAME }}
STACK_EXCHANGE_ID: ${{ secrets.stack_exchange_id }}
STACK_EXCHANGE_ACCESS_TOKEN: ${{ secrets.stack_exchange_access_token }}
AZURE_APP_CONFIGURATION_CONNECTION_STRING: ${{ secrets.azure_app_configuration_connection_string }}
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/CI-time-tracker-ui.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ jobs:
SCOPES: ${{ secrets.SCOPES }}
CLIENT_ID: ${{ secrets.CLIENT_ID }}
CLIENT_URL : ${{ secrets.CLIENT_URL }}
AUTH_URL: ${{ secrets.AUTH_URL }}
AUTH_APP_NAME: ${{ secrets.AUTH_APP_NAME }}
STACK_EXCHANGE_ID: ${{ secrets.STACK_EXCHANGE_ID }}
STACK_EXCHANGE_ACCESS_TOKEN: ${{ secrets.STACK_EXCHANGE_ACCESS_TOKEN }}
AZURE_APP_CONFIGURATION_CONNECTION_STRING: ${{ secrets.AZURE_APP_CONFIGURATION_CONNECTION_STRING }}
Expand Down
6 changes: 5 additions & 1 deletion .github/workflows/time-tracker-ui-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,16 @@ jobs:
with:
ssh-private-key: ${{ secrets.INFRA_TERRAFORM_MODULES_SSH_PRIV_KEY }}

- name: Unlock DEV secrets
uses: sliteteam/[email protected]
env:
GIT_CRYPT_KEY: ${{ secrets.GIT_CRYPT_KEY_DEFAULT }}

- name: build docker
run: make build

- name: Running tests
run: |
chmod -R 777 ./$home
make test
- name: Generate coverage report
env:
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ remove: ## Delete container timetracker_ui.
.PHONY: test
test: ## Run all tests on docker container timetracker_ui at the CLI.
docker-compose build timetracker_ui_test
docker-compose up -d timetracker_ui_test
docker-compose --env-file=.dev.env up -d timetracker_ui_test
docker logs -f timetracker_ui_test

.PHONY: testdev
Expand Down
4 changes: 4 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ services:
timetracker_ui:
container_name: timetracker_ui
image: timetracker_ui
env_file:
- .dev.env
build:
context: .
dockerfile: ./Docker/Dockerfile.dev
Expand All @@ -14,6 +16,8 @@ services:
API_URL: ${API_URL}
CLIENT_ID: ${CLIENT_ID}
CLIENT_URL: ${CLIENT_URL}
AUTH_URL: ${AUTH_URL}
AUTH_APP_NAME: ${AUTH_APP_NAME}
SCOPES: ${SCOPES}
STACK_EXCHANGE_ID: ${STACK_EXCHANGE_ID}
STACK_EXCHANGE_ACCESS_TOKEN: ${STACK_EXCHANGE_ACCESS_TOKEN}
Expand Down
2 changes: 2 additions & 0 deletions scripts/populate-keys.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ echo "API_URL='$API_URL'" >> .env
echo "AUTHORITY='$AUTHORITY'" >> .env
echo "CLIENT_ID='$CLIENT_ID'" >> .env
echo "CLIENT_URL='$CLIENT_URL'" >> .env
echo "AUTH_URL='$AUTH_URL'" >> .env
echo "AUTH_APP_NAME='$AUTH_APP_NAME'" >> .env
echo "SCOPES='$SCOPES'" >> .env
echo "STACK_EXCHANGE_ID='$STACK_EXCHANGE_ID'" >> .env
echo "STACK_EXCHANGE_ACCESS_TOKEN='$STACK_EXCHANGE_ACCESS_TOKEN'" >> .env
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export class ActivityService {
constructor(private http: HttpClient) {}

getActivities(): Observable<Activity[]> {
return this.http.get<Activity[]>(this.baseUrl);
return this.http.get<Activity[]>(this.baseUrl, { withCredentials: true });
}

createActivity(activityData): Observable<any> {
Expand All @@ -23,12 +23,12 @@ export class ActivityService {
tenant_id: '4225ab1e-1033-4a5f-8650-0dd4950f38c8',
};

return this.http.post(this.baseUrl, body);
return this.http.post(this.baseUrl, body, { withCredentials: true });
}

deleteActivity(acitivityId: string): Observable<any> {
const url = `${this.baseUrl}/${acitivityId}`;
return this.http.delete(url);
return this.http.delete(url, { withCredentials: true });
}

updateActivity(activityData): Observable<any> {
Expand All @@ -38,6 +38,6 @@ export class ActivityService {
...activityData,
};

return this.http.put(url, body);
return this.http.put(url, body, { withCredentials: true });
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,20 @@ export class ProjectTypeService {

getProjectTypes(customerId: any): Observable<ProjectType[]> {
const params = new HttpParams().set('customer_id', customerId.customerId);
return this.http.get<ProjectType[]>(this.baseUrl, { params });
return this.http.get<ProjectType[]>(this.baseUrl, { params, withCredentials: true });
}

createProjectType(projectTypeData): Observable<any> {
return this.http.post(this.baseUrl, projectTypeData);
return this.http.post(this.baseUrl, projectTypeData, { withCredentials: true });
}

deleteProjectType(projectTypeId: string): Observable<any> {
const url = `${this.baseUrl}/${projectTypeId}`;
return this.http.delete(url);
return this.http.delete(url, { withCredentials: true });
}

updateProjectType(projectTypeData): Observable<any> {
const url = `${this.baseUrl}/${projectTypeData.id}`;
return this.http.put(url, projectTypeData);
return this.http.put(url, projectTypeData, { withCredentials: true });
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,19 @@ export class ProjectService {

getProjects(customerId: any): Observable<Project[]> {
const params = new HttpParams().set('customer_id', customerId.customerId);
return this.http.get<Project[]>(this.url, { params });
return this.http.get<Project[]>(this.url, { params, withCredentials: true });
}

getAllProjects(): Observable<Project[]> {
return this.http.get<Project[]>(this.url);
return this.http.get<Project[]>(this.url, { withCredentials: true });
}

getRecentProjects(): Observable<Project[]> {
return this.http.get<Project[]>(`${this.url}/recent`);
return this.http.get<Project[]>(`${this.url}/recent`, { withCredentials: true });
}

createProject(projectData): Observable<any> {
return this.http.post<Project[]>(this.url, projectData);
return this.http.post<Project[]>(this.url, projectData, { withCredentials: true });
}

updateProject(projectData): Observable<any> {
Expand All @@ -39,12 +39,12 @@ export class ProjectService {
projectData.status = 1;
}
}
return this.http.put(`${this.url}/${id}`, projectData);
return this.http.put(`${this.url}/${id}`, projectData, { withCredentials: true });
}

deleteProject(projectId: string): Observable<any> {
return this.isDevelopmentOrProd
? this.http.put(`${this.url}/${projectId}`, { status: 0 })
: this.http.delete(`${this.url}/${projectId}`);
: this.http.delete(`${this.url}/${projectId}`, { withCredentials: true });
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,20 @@ export class CustomerService {
constructor(private http: HttpClient) {}

createCustomer(customerData): Observable<any> {
return this.http.post(this.baseUrl, customerData);
return this.http.post(this.baseUrl, customerData, { withCredentials: true });
}

getCustomers(): Observable<any> {
return this.http.get(this.baseUrl);
return this.http.get(this.baseUrl, { withCredentials: true });
}

deleteCustomer(customerId: string): Observable<any> {
const url = `${this.baseUrl}/${customerId}`;
return this.http.delete(url);
return this.http.delete(url, { withCredentials: true });
}

updateCustomer(customerData): Observable<any> {
const url = `${this.baseUrl}/${customerData.id}`;
return this.http.put(url, customerData);
return this.http.put(url, customerData, { withCredentials: true });
}
}
11 changes: 1 addition & 10 deletions src/app/modules/login/login.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,6 @@ <h3>Please log in</h3>
<button (click)="login() " class="btn btn-primary">login</button>
</div>
<div *ngIf="!isProduction">
<div
id="g_id_onload"
[attr.data-client_id]="cliendId"
data-callback="handleCredentialResponse">
</div>
<div
class="g_id_signin"
data-theme="filled_blue"
data-type="standard">
</div>
<button class="btn btn-primary" (click)="loginAuth()">Login</button>
</div>
</div>
10 changes: 10 additions & 0 deletions src/app/modules/login/login.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,16 @@ describe('LoginComponent', () => {
expect(component).toBeTruthy();
});

it('should set local storage when the component is initialized and is not legacy production', inject([Router], (router: Router) => {
component.isProduction = false;
spyOn(loginService, 'getUser').and.returnValue(of(userTest));
spyOn(loginService, 'setLocalStorage');

component.ngOnInit();

expect(loginService.setLocalStorage).toHaveBeenCalled();
}));

it('should sign up or login with google if is not logged-in into the app on Production', inject([Router], (router: Router) => {
spyOn(azureAdB2CService, 'isLogin').and.returnValue(false);
spyOn(azureAdB2CService, 'setCookies').and.returnValue();
Expand Down
59 changes: 13 additions & 46 deletions src/app/modules/login/login.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ declare global {
export class LoginComponent implements OnInit {
isProduction = environment.production === EnvironmentType.TT_PROD_LEGACY;
cliendId = CLIENT_URL;
authUrl = environment.authUrl;
authAppName = environment.authAppName;
auth2: any;


Expand All @@ -34,54 +36,16 @@ export class LoginComponent implements OnInit {
private ngZone?: NgZone
) {}


googleAuthSDK() {
const sdkLoaded = 'googleSDKLoaded';
const gapi = 'gapi';

(window as any)[sdkLoaded] = () => {
(window as any)[gapi].load('auth2', () => {
this.auth2 = ( window as any)[gapi].auth2.init({
client_id: this.cliendId,
plugin_name: 'login',
cookiepolicy: 'single_host_origin',
scope: 'profile email'
});
});
};

(async (d, s, id) => {
const keyGoogle = 'src';
const gjs = d.getElementsByTagName(s)[1];
let js = gjs;
if (d.getElementById(id)) { return; }
js = d.createElement(s); js.id = id;
js[keyGoogle] = 'https://accounts.google.com/gsi/client';
gjs.parentNode.insertBefore(js, gjs);
})(document, 'script', 'async defer');
}

ngOnInit() {

this.googleAuthSDK();
this.loginService.isLogin().subscribe(isLogin => {
if (isLogin) {
this.router.navigate(['']);
}
if (!this.isProduction) {
this.loginService.getUser(null).subscribe((resp) => {
this.loginService.setCookies();
const tokenObject = JSON.stringify(resp);
const tokenJson = JSON.parse(tokenObject);
this.loginService.setLocalStorage('user', tokenJson.token);
this.ngZone.run(() => this.router.navigate(['']));
});

window.handleCredentialResponse = (response) => {
const {credential = ''} = response;
this.featureToggleCookiesService.setCookies();
this.loginService.setLocalStorage('idToken', credential);
this.loginService.getUser(credential).subscribe((resp) => {
this.loginService.setCookies();
const tokenObject = JSON.stringify(resp);
const tokenJson = JSON.parse(tokenObject);
this.loginService.setLocalStorage('user', tokenJson.token);
this.ngZone.run(() => this.router.navigate(['']));
});
};
}
}

login(): void {
Expand All @@ -103,4 +67,7 @@ export class LoginComponent implements OnInit {
}
}

loginAuth() {
window.location.href = `${this.authUrl}/authn/login/${this.authAppName}`;
}
}
11 changes: 9 additions & 2 deletions src/app/modules/login/services/login.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { TestBed } from '@angular/core/testing';
import { JwtHelperService } from '@auth0/angular-jwt';
import { SocialAuthService } from 'angularx-social-login';
import { CookieService } from 'ngx-cookie-service';
import { RouterTestingModule } from '@angular/router/testing';
import { of } from 'rxjs';

import { LoginService } from './login.service';
Expand All @@ -23,11 +24,11 @@ describe('LoginService', () => {

beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
imports: [HttpClientTestingModule, RouterTestingModule.withRoutes([])],
providers: [
{ providers: CookieService, useValue: cookieStoreStub },
{ provide: SocialAuthService, useValue: socialAuthServiceStub },
{ provide: HttpClient, useValue: httpClientSpy }
{ provide: HttpClient, useValue: httpClientSpy },
],
});
service = TestBed.inject(LoginService);
Expand Down Expand Up @@ -122,12 +123,18 @@ describe('LoginService', () => {

it('should logout with social angularx-social-login', () => {
spyOn(cookieService, 'deleteAll').and.returnValue();
spyOn(service, 'invalidateSessionCookie').and.returnValue(of(true));

service.logout();

expect(localStorage.clear).toHaveBeenCalled();
expect(cookieService.deleteAll).toHaveBeenCalled();
});

it('should return an http observable when call invalidateSessionCooke', () => {
const result = service.invalidateSessionCookie();
expect(result).toBeDefined();
});

it('should call cookieService when app is isLegacyProd', () => {
service.isLegacyProd = true;
Expand Down
Loading