Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
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
2 changes: 1 addition & 1 deletion apps/vulnerability-checker/src/app/app.component.html
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
<gc-ui-toolbar>
</gc-ui-toolbar>
</gc-ui-toolbar>
4 changes: 3 additions & 1 deletion apps/vulnerability-checker/src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,7 @@ import { Component } from '@angular/core';
styleUrls: ['./app.component.scss']
})
export class AppComponent {
title = 'vulnerability-checker';

constructor() {
}
}
9 changes: 7 additions & 2 deletions apps/vulnerability-checker/src/app/app.module.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
import { UiLibrariesModule } from '@gc/ui-libraries';
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';

import { MaterialModule } from '@gc/material';
import { CoreDataModule } from '@gc/core-data';
import { UiLibrariesModule } from '@gc/ui-libraries';

@NgModule({
declarations: [AppComponent],
imports: [
BrowserModule,
BrowserAnimationsModule,
MaterialModule,
CoreDataModule,
UiLibrariesModule
],
declarations: [AppComponent],
providers: [],
bootstrap: [AppComponent]
})
Expand Down
15 changes: 14 additions & 1 deletion libs/core-data/src/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,14 @@
export * from './lib/core-data.module';
export { CoreDataModule } from './lib/core-data.module';

// Models
export { Repository, emptyRepository, Visibility } from './lib/repositories/repositories';
export { User, emptyUser } from './lib/user/user.model';


// Services
export { AuthGuard } from './lib/auth/auth-guard';
export { AuthService } from './lib/auth/auth.service';
export { NotifyService } from './lib/notify/notify.service';
export { RepositoriesService } from './lib/repositories/repositories.service';
export { TokenInterceptor } from './lib/auth/token-interceptor';
export { UserService } from './lib/user/user.service';
23 changes: 21 additions & 2 deletions libs/core-data/src/lib/auth/auth-guard.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,28 @@
import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree, Router } from '@angular/router';

import { Observable } from 'rxjs';

import { AuthService } from './auth.service';

@Injectable({
providedIn: 'root'
})
export class AuthGuard {
export class AuthGuard implements CanActivate {
constructor(
private router: Router,
private authService: AuthService
) {}

canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
if (!this.authService.isAuthenticated$.value) {
this.router.navigate(['/login']);
return false;
}
return true;
}

constructor() { }
}
32 changes: 31 additions & 1 deletion libs/core-data/src/lib/auth/auth.service.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,39 @@
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Router } from '@angular/router';

import { tap } from 'rxjs/operators';
import { BehaviorSubject } from 'rxjs';

export const TOKEN_NAME = 'gh:auth:token';

@Injectable({
providedIn: 'root'
})
export class AuthService {
isAuthenticated$ = new BehaviorSubject(false);

constructor(
private router: Router,
private http: HttpClient
) {
this.setToken(this.getToken());
}

handleRedirectCallback(code: string) {
const loginURL = `https://gh-auth-server.herokuapp.com/authenticate/${code}`;
return this.http.get(loginURL).pipe(
tap((res: {token: string}) => this.setToken(res.token)),
tap(() => this.router.navigate(['']))
);
}

setToken(token) {
localStorage.setItem(TOKEN_NAME, token);
this.isAuthenticated$.next(token !== '' || token !== null || token !== undefined);
}

constructor() { }
getToken() {
return localStorage.getItem(TOKEN_NAME);
}
}
35 changes: 33 additions & 2 deletions libs/core-data/src/lib/auth/token-interceptor.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,40 @@
import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { HttpInterceptor, HttpHandler, HttpRequest, HttpEvent, HttpErrorResponse } from '@angular/common/http';

import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';

import { AuthService } from './auth.service';

@Injectable({
providedIn: 'root'
})
export class TokenInterceptor {
export class TokenInterceptor implements HttpInterceptor {
constructor(
private router: Router,
private authService: AuthService
) { }

intercept(
request: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
request = request.clone({
setHeaders: {
Authorization: `bearer ${this.authService.getToken()}`
}
});

return next.handle(request).pipe(
tap(() => {}, (error: HttpErrorResponse) => this.handleUnAuth(error))
);
}

handleUnAuth(error: HttpErrorResponse) {
if (error.status === 401) {
this.router.navigate(['login']);
}
}

constructor() { }
}
31 changes: 29 additions & 2 deletions libs/core-data/src/lib/core-data.module.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,34 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { HttpClientModule, HttpHeaders, HTTP_INTERCEPTORS } from '@angular/common/http';

import { APOLLO_OPTIONS, ApolloModule } from 'apollo-angular';
import { HttpLink, HttpLinkModule } from 'apollo-angular-link-http';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { TokenInterceptor } from './auth/token-interceptor';

const uri = 'https://api.github.com/graphql';

export function createApollo(httpLink: HttpLink) {
return {
link: httpLink.create({ uri }),
cache: new InMemoryCache()
}
}

@NgModule({
imports: [CommonModule]
imports: [HttpClientModule],
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: TokenInterceptor,
multi: true,
},
{
provide: APOLLO_OPTIONS,
useFactory: createApollo,
deps: [HttpLink]
}
],
exports: [ApolloModule, HttpLinkModule]
})
export class CoreDataModule {}
37 changes: 37 additions & 0 deletions libs/core-data/src/lib/repositories/repositories.graphql.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import gql from 'graphql-tag';

const repositoryFragment = gql`
fragment repositoryFragment on Repository {
id
name
description
homepageUrl
url
forkCount
isPrivate
isFork
languages(first: 1) {
nodes {
name
color
id
}
}
createdAt
updatedAt
pushedAt
}
`;

export const repositoriesQuery = gql`
query repositoriesQuery($login: String!) {
Comment thread
eccentricnode marked this conversation as resolved.
user(login: $login) {
repositories(first: 100, orderBy: {field: CREATED_AT, direction: DESC}) {
nodes {
...repositoryFragment
}
}
}
}
${repositoryFragment}
`;
24 changes: 23 additions & 1 deletion libs/core-data/src/lib/repositories/repositories.service.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,31 @@

import { Injectable } from '@angular/core';
import { Apollo } from 'apollo-angular';
import { map } from 'rxjs/operators';
import { ApolloQueryResult } from 'apollo-client';
import { UserService } from '../user/user.service';
import { repositoriesQuery } from './repositories.graphql';

@Injectable({
providedIn: 'root'
})
export class RepositoriesService {

constructor() { }
constructor(
private apollo: Apollo,
private userService: UserService
) { }

all() {
const login = this.userService.getUsername();
return this.apollo.mutate({
mutation: repositoriesQuery,
variables: {
login
}
}).pipe(
map((response: ApolloQueryResult<any>) => response.data.user.repositories.nodes),
map((repositories: any[]) => repositories.map((repo) => ({ ...repo, languages: repo.languages.nodes[0] })))
)
}
}
52 changes: 52 additions & 0 deletions libs/core-data/src/lib/repositories/repositories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
export interface Repository {
id: string;
name: string;
description: string;
homepageUrl: string;
url: string;
forkCount: number;
isPrivate: boolean;
isFork: boolean;
languages: Language;
createdAt: string;
updatedAt: string;
pushedAt: string;
}

export interface RepositoryInput {
name: string,
visibility: Visibility,
description: string,
hasIssuesEnabled: boolean
}

export enum Visibility {
PRIVATE = 'PRIVATE',
PUBLIC = 'PUBLIC',
INTERNAL = 'INTERNAL'
}

interface Language {
id: string;
name: string;
color: string;
}

export const emptyRepository: Repository = {
id: null,
name: '',
description: '',
homepageUrl: '',
url: '',
forkCount: 0,
isPrivate: false,
isFork: false,
languages: {
id: null,
name: '',
color: ''
},
createdAt: '',
updatedAt: '',
pushedAt: ''
};
30 changes: 30 additions & 0 deletions libs/core-data/src/lib/user/user.graphql.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import gql from 'graphql-tag';

const userFragment = gql`
fragment userFragment on User {
id
avatarUrl
name
login
url
email
bio
}
`;

export const getUsernameQuery = gql`
query getUsernameQuery {
viewer {
login
}
}
`;

export const usersQuery = gql`
query usersQuery($login: String!) {
user(login: $login) {
...userFragment
}
}
${userFragment}
`;
19 changes: 19 additions & 0 deletions libs/core-data/src/lib/user/user.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
export interface User {
id: string;
avatarUrl: string;
name: string;
login: string;
url: string;
email: string;
bio: string;
}

export const emptyUser: User = {
id: null,
avatarUrl: '',
name: '',
login: '',
url: '',
email: '',
bio: ''
}
Loading