From 2182b6c1580d31ddffe9d5bbfe2d562404667d8f Mon Sep 17 00:00:00 2001 From: TheDonDope Date: Mon, 10 Oct 2016 19:15:13 +0200 Subject: [PATCH 01/10] chore(build): provide release utilities Provide release utility scripts for the following tasks: - Getting `next-version` for bumping: `$ npm run bump-version` - Generating `CHANGELOG.md`: `$ npm run changelog` - Drafting and publishing a GitHub release: `$ npm run github-release` --- README.md | 32 ++++++++++++++++++++++++++++++++ package.json | 5 ++++- 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 73a8f51..d14a342 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,38 @@ Before running the tests make sure you are serving the app via `ng serve`. Run `ng github-pages:deploy` to deploy to Github Pages. +## Commit Message Format + +This project follows the [angular commit-message convention](https://github.com/conventional-changelog/conventional-changelog-angular/blob/master/convention.md). + +## Versioning + +This project follows the [Semantic Versioning 2.0.0](http://semver.org/) specification. + +## Bumping Version Number + +If you follow semantic versioning and use the [angular commit-message convention](https://github.com/conventional-changelog/conventional-changelog-angular/blob/master/convention.md), you can use the following npm task to get the appropiate next version number + +```bash +$ npm run bump-version +``` + +## Releasing + +You can use the following workflow to ease your release process: + +*Note: The following scripts use the npm-packages [conventional-github-releaser](https://github.com/conventional-changelog/conventional-github-releaser), [conventional-recommended-bump](https://github.com/conventional-changelog/conventional-recommended-bump) and [standard-changelog](https://github.com/conventional-changelog/standard-changelog). Make sure you install them first by running: `npm install -g conventional-github-releaser conventional-recommended-bump standard-changelog`. Furthermore, [gitflow](https://github.com/nvie/gitflow) is partially used for the following commands* + +0. Given your project was initialized with `$ git flow init` and your current branch being `develop` is ready to be released, do the following +1. Get your next-version number:`$ npm run bump-version` +2. Start your next-release: `$ git flow release start ` +3. Bump the version number in your `package.json` with the version from step 1 +4. Generate your `CHANGELOG.md`: `$ npm run changelog` +5. Make your release commit: `$ git add --all && git commit -m 'chore(release): '` +6. Finish your release: `$ git flow release finish ` +7. Push your branches and tags to GitHub: `$ git push origin master && git push origin develop && git push origin --tags` +8. Draft and publish your GitHub Relase: `$ npm run github-release` + ## Further help To get more help on the `angular-cli` use `ng --help` or go check out the [Angular-CLI README](https://github.com/angular/angular-cli/blob/master/README.md). diff --git a/package.json b/package.json index 1d7e461..9045041 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,10 @@ "lint": "tslint \"src/**/*.ts\"", "test": "ng test", "pree2e": "webdriver-manager update", - "e2e": "protractor" + "e2e": "protractor", + "bump-version": "conventional-recommended-bump", + "changelog": "standard-changelog", + "github-release": "conventional-github-releaser -p angular -r 0" }, "private": true, "dependencies": { From 39a205f37a38cb2681d34e9e9e85add9f1130f15 Mon Sep 17 00:00:00 2001 From: TheDonDope Date: Mon, 10 Oct 2016 19:23:21 +0200 Subject: [PATCH 02/10] chore(deps): install bootstrap Install the Bootstrap NPM package dependency to utilise it for the SCSS styling of the application --- README.md | 4 ++++ angular-cli.json | 9 +++++++-- package.json | 1 + 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d14a342..85574a1 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,10 @@ This project was generated with [angular-cli](https://github.com/angular/angular-cli) version 1.0.0-beta.17. +It uses the following npm packages (version numbers current as of 2016-10-10): + +- [Bootstrap 4.0.0-alpha.4](https://www.npmjs.com/package/bootstrap): Used for the SCSS styling of the application + ## Development server Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files. diff --git a/angular-cli.json b/angular-cli.json index 835adb3..f29aeb9 100644 --- a/angular-cli.json +++ b/angular-cli.json @@ -15,9 +15,14 @@ "prefix": "cru", "mobile": false, "styles": [ - "styles.scss" + "styles.scss", + "../node_modules/bootstrap/scss/bootstrap.scss" + ], + "scripts": [ + "../node_modules/jquery/dist/jquery.js", + "../node_modules/tether/dist/js/tether.js", + "../node_modules/bootstrap/dist/js/bootstrap.js" ], - "scripts": [], "environments": { "source": "environments/environment.ts", "dev": "environments/environment.ts", diff --git a/package.json b/package.json index 9045041..e31a791 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "@angular/platform-browser": "~2.0.0", "@angular/platform-browser-dynamic": "~2.0.0", "@angular/router": "~3.0.0", + "bootstrap": "^4.0.0-alpha.4", "core-js": "^2.4.1", "rxjs": "5.0.0-beta.12", "ts-helpers": "^1.1.1", From 6449ddd58200a49be4bcda6b0d260de33ac6cd05 Mon Sep 17 00:00:00 2001 From: TheDonDope Date: Mon, 10 Oct 2016 19:30:14 +0200 Subject: [PATCH 03/10] feat(styling): configure bootstrap Configure the following SCSS styling properties: - Fonts - Flexbox - Bootstrap --- src/app/app.component.html | 8 +++++--- src/styles.scss | 7 ++++++- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/app/app.component.html b/src/app/app.component.html index b6931b5..425cad5 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -1,3 +1,5 @@ -

- {{title}} -

+
+

+ {{title}} +

+
diff --git a/src/styles.scss b/src/styles.scss index e50a47e..e01d151 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -1 +1,6 @@ -/* You can add global styles to this file, and also import other style files */ \ No newline at end of file +/* You can add global styles to this file, and also import other style files */ +@import url('https://fonts.googleapis.com/css?family=Roboto:500'); +$font-family-sans-serif: 'Roboto', 'Helvetica Neue', Helvetica, Arial, sans-serif; + +$enable-flex: true; +@import '../node_modules/bootstrap/scss/bootstrap'; From f69c2a48df9ee73a58884d2a68ad178e6a7a7d45 Mon Sep 17 00:00:00 2001 From: TheDonDope Date: Mon, 10 Oct 2016 19:45:15 +0200 Subject: [PATCH 04/10] chore(deps): install font-awesome Install the Font-Awesome NPM package dependency to utilise as the glyphicon font of the application --- README.md | 1 + angular-cli.json | 3 ++- package.json | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 85574a1..1f9fc49 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ This project was generated with [angular-cli](https://github.com/angular/angular It uses the following npm packages (version numbers current as of 2016-10-10): - [Bootstrap 4.0.0-alpha.4](https://www.npmjs.com/package/bootstrap): Used for the SCSS styling of the application +- [Font-Awesome 4.6.3](https://www.npmjs.com/package/font-awesome): Used as the glyphicon font of the application ## Development server Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files. diff --git a/angular-cli.json b/angular-cli.json index f29aeb9..0b898cb 100644 --- a/angular-cli.json +++ b/angular-cli.json @@ -16,7 +16,8 @@ "mobile": false, "styles": [ "styles.scss", - "../node_modules/bootstrap/scss/bootstrap.scss" + "../node_modules/bootstrap/scss/bootstrap.scss", + "../node_modules/font-awesome/scss/font-awesome.scss" ], "scripts": [ "../node_modules/jquery/dist/jquery.js", diff --git a/package.json b/package.json index e31a791..df54bb7 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "@angular/router": "~3.0.0", "bootstrap": "^4.0.0-alpha.4", "core-js": "^2.4.1", + "font-awesome": "^4.6.3", "rxjs": "5.0.0-beta.12", "ts-helpers": "^1.1.1", "zone.js": "^0.6.23" From 4c496bcaa6eb6254d44530f4cb692f4c6cfe2031 Mon Sep 17 00:00:00 2001 From: TheDonDope Date: Mon, 10 Oct 2016 19:47:32 +0200 Subject: [PATCH 05/10] feat(styling): configure font-awesome Configure the following SCSS styling properties: - Font-Awesome --- src/styles.scss | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/styles.scss b/src/styles.scss index e01d151..73cd335 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -4,3 +4,6 @@ $font-family-sans-serif: 'Roboto', 'Helvetica Neue', Helvetica, Arial, sans-seri $enable-flex: true; @import '../node_modules/bootstrap/scss/bootstrap'; + +$fa-font-path: '../node_modules/font-awesome/fonts'; +@import '../node_modules/font-awesome/scss/font-awesome'; From 7f0d496320db130a4e13f82cc11c7c07373aa7a0 Mon Sep 17 00:00:00 2001 From: TheDonDope Date: Mon, 10 Oct 2016 19:53:07 +0200 Subject: [PATCH 06/10] chore(deps): install moment Install the Moment NPM package dependency to provide utilites for date/time manipulation --- README.md | 1 + angular-cli.json | 3 ++- package.json | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1f9fc49..8e766e4 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ It uses the following npm packages (version numbers current as of 2016-10-10): - [Bootstrap 4.0.0-alpha.4](https://www.npmjs.com/package/bootstrap): Used for the SCSS styling of the application - [Font-Awesome 4.6.3](https://www.npmjs.com/package/font-awesome): Used as the glyphicon font of the application +- [Moment 2.15.1](https://www.npmjs.com/package/moment): Used for date/time manipulation *(Note: The npm package already includes the types for moment so you do not need to add it with `npm install @types/moment --save-dev`)* ## Development server Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files. diff --git a/angular-cli.json b/angular-cli.json index 0b898cb..f085535 100644 --- a/angular-cli.json +++ b/angular-cli.json @@ -22,7 +22,8 @@ "scripts": [ "../node_modules/jquery/dist/jquery.js", "../node_modules/tether/dist/js/tether.js", - "../node_modules/bootstrap/dist/js/bootstrap.js" + "../node_modules/bootstrap/dist/js/bootstrap.js", + "../node_modules/moment/moment.js" ], "environments": { "source": "environments/environment.ts", diff --git a/package.json b/package.json index df54bb7..61737d0 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "bootstrap": "^4.0.0-alpha.4", "core-js": "^2.4.1", "font-awesome": "^4.6.3", + "moment": "^2.15.1", "rxjs": "5.0.0-beta.12", "ts-helpers": "^1.1.1", "zone.js": "^0.6.23" From a9f2ad8d43b7b3e380679642054d3b8a6a5fec94 Mon Sep 17 00:00:00 2001 From: TheDonDope Date: Mon, 10 Oct 2016 20:00:34 +0200 Subject: [PATCH 07/10] style(readme): add styleguide Add information about the projects conformity to the Official Angular Styleguide as well as a fancy badge --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 8e766e4..2b52a59 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # Crudular +[![Angular Style Guide](https://mgechev.github.io/angular2-style-guide/images/badge.svg)](https://angular.io/styleguide) + This project was generated with [angular-cli](https://github.com/angular/angular-cli) version 1.0.0-beta.17. It uses the following npm packages (version numbers current as of 2016-10-10): @@ -8,6 +10,8 @@ It uses the following npm packages (version numbers current as of 2016-10-10): - [Font-Awesome 4.6.3](https://www.npmjs.com/package/font-awesome): Used as the glyphicon font of the application - [Moment 2.15.1](https://www.npmjs.com/package/moment): Used for date/time manipulation *(Note: The npm package already includes the types for moment so you do not need to add it with `npm install @types/moment --save-dev`)* +It follows the [Official Angular Styleguide](https://angular.io/styleguide). + ## Development server Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files. From 57bc688e959876f7ecc78bfe84287dd34fefa321 Mon Sep 17 00:00:00 2001 From: TheDonDope Date: Mon, 10 Oct 2016 20:06:14 +0200 Subject: [PATCH 08/10] feat(routing): provide app routing module Provide an application level routing module as sole registry for all routes of the application. Feature routes get imported through their respective modules and then provided by the `AppRoutingModule` --- src/app/app.module.ts | 16 +++++++++++----- src/app/app.routing.ts | 17 +++++++++++++++++ 2 files changed, 28 insertions(+), 5 deletions(-) create mode 100644 src/app/app.routing.ts diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 67ae491..3cb5ccd 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -1,18 +1,24 @@ -import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { HttpModule } from '@angular/http'; +import { RouterModule } from '@angular/router'; +import { BrowserModule } from '@angular/platform-browser'; import { AppComponent } from './app.component'; +import { AppRoutingModule } from './app.routing'; + @NgModule({ - declarations: [ - AppComponent - ], + declarations: [AppComponent], imports: [ + // @angular/platform-browser BrowserModule, + // @angular/forms FormsModule, - HttpModule + // @angular/http + HttpModule, + // app.routing + AppRoutingModule ], providers: [], bootstrap: [AppComponent] diff --git a/src/app/app.routing.ts b/src/app/app.routing.ts new file mode 100644 index 0000000..9d79c7f --- /dev/null +++ b/src/app/app.routing.ts @@ -0,0 +1,17 @@ +import { NgModule } from '@angular/core'; +import { Routes, RouterModule } from '@angular/router'; + +const AppRoutes: Routes = [ + +]; + +/** + * This module provides all the routes of the application. Any feature routes are imported through their respective + * module and added to the `AppRoutes` array. + */ +@NgModule({ + imports: [RouterModule.forRoot(AppRoutes)], + exports: [RouterModule], + providers: [] +}) +export class AppRoutingModule { } From cb720805b182865ba7d0accb949206e77a80aacd Mon Sep 17 00:00:00 2001 From: TheDonDope Date: Mon, 10 Oct 2016 20:36:40 +0200 Subject: [PATCH 09/10] feat(jwt): provide login, home and shared module Provide a login module with the following features: - Provide a login view to authenticate with a remote api Provide a home module with the following features: - Provide a home view showing the user information about his JWT token Provide a shared module with the following features: - Manage a JWT authenticity token to use for calls of protected remote api methods - Provide a dynamic authentication-based navigation --- README.md | 10 ++ src/app/app.component.html | 5 +- src/app/app.component.ts | 8 +- src/app/app.module.ts | 11 ++- src/app/app.routing.ts | 6 +- src/app/home/home.component.html | 18 ++++ src/app/home/home.component.scss | 3 + src/app/home/home.component.spec.ts | 11 +++ src/app/home/home.component.ts | 35 +++++++ src/app/home/home.module.ts | 12 +++ src/app/home/home.routing.ts | 8 ++ src/app/home/index.ts | 2 + src/app/login/index.ts | 2 + src/app/login/login.component.html | 42 +++++++++ src/app/login/login.component.scss | 0 src/app/login/login.component.spec.ts | 11 +++ src/app/login/login.component.ts | 52 +++++++++++ src/app/login/login.module.ts | 12 +++ src/app/login/login.routing.ts | 7 ++ .../authentication/authentication.guard.ts | 32 +++++++ .../authentication/authentication.module.ts | 20 ++++ .../authentication/authentication.service.ts | 91 +++++++++++++++++++ src/app/shared/authentication/index.ts | 2 + src/app/shared/index.ts | 2 + src/app/shared/navigation/index.ts | 1 + .../navigation/navigation.component.html | 6 ++ .../navigation/navigation.component.scss | 0 .../navigation/navigation.component.spec.ts | 11 +++ .../shared/navigation/navigation.component.ts | 42 +++++++++ .../shared/navigation/navigation.module.ts | 14 +++ src/app/shared/shared.module.ts | 31 +++++++ src/environments/environment.prod.ts | 3 +- src/environments/environment.ts | 3 +- 33 files changed, 505 insertions(+), 8 deletions(-) create mode 100644 src/app/home/home.component.html create mode 100644 src/app/home/home.component.scss create mode 100644 src/app/home/home.component.spec.ts create mode 100644 src/app/home/home.component.ts create mode 100644 src/app/home/home.module.ts create mode 100644 src/app/home/home.routing.ts create mode 100644 src/app/home/index.ts create mode 100644 src/app/login/index.ts create mode 100644 src/app/login/login.component.html create mode 100644 src/app/login/login.component.scss create mode 100644 src/app/login/login.component.spec.ts create mode 100644 src/app/login/login.component.ts create mode 100644 src/app/login/login.module.ts create mode 100644 src/app/login/login.routing.ts create mode 100644 src/app/shared/authentication/authentication.guard.ts create mode 100644 src/app/shared/authentication/authentication.module.ts create mode 100644 src/app/shared/authentication/authentication.service.ts create mode 100644 src/app/shared/authentication/index.ts create mode 100644 src/app/shared/navigation/index.ts create mode 100644 src/app/shared/navigation/navigation.component.html create mode 100644 src/app/shared/navigation/navigation.component.scss create mode 100644 src/app/shared/navigation/navigation.component.spec.ts create mode 100644 src/app/shared/navigation/navigation.component.ts create mode 100644 src/app/shared/navigation/navigation.module.ts create mode 100644 src/app/shared/shared.module.ts diff --git a/README.md b/README.md index 2b52a59..fb1624c 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,17 @@ It uses the following npm packages (version numbers current as of 2016-10-10): It follows the [Official Angular Styleguide](https://angular.io/styleguide). +## Features + +The application provides the following features: + +- Provide a login view to authenticate with a remote api +- Manage a JWT authenticity token to use for calls of protected remote api methods +- Provide a home view showing the user information about his JWT token +- Provide a dynamic authentication-based navigation + ## Development server + Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files. ## Code scaffolding diff --git a/src/app/app.component.html b/src/app/app.component.html index 425cad5..227c4bb 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -1,5 +1,4 @@
-

- {{title}} -

+ +
diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 0567822..f819bd8 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,10 +1,16 @@ import { Component } from '@angular/core'; +import { environment } from '../environments/environment'; + @Component({ selector: 'cru-root', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'] }) export class AppComponent { - title = 'cru works!'; + + constructor() { + console.log(JSON.stringify(environment)); + } + } diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 3cb5ccd..a713782 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -6,6 +6,9 @@ import { BrowserModule } from '@angular/platform-browser'; import { AppComponent } from './app.component'; +import { HomeModule } from './home/home.module'; +import { LoginModule } from './login/login.module'; +import { SharedModule } from './shared/shared.module'; import { AppRoutingModule } from './app.routing'; @NgModule({ @@ -18,7 +21,13 @@ import { AppRoutingModule } from './app.routing'; // @angular/http HttpModule, // app.routing - AppRoutingModule + AppRoutingModule, + // shared/shared.module + SharedModule, + // home/home.module + HomeModule, + // login/login.module + LoginModule ], providers: [], bootstrap: [AppComponent] diff --git a/src/app/app.routing.ts b/src/app/app.routing.ts index 9d79c7f..2cd4c9a 100644 --- a/src/app/app.routing.ts +++ b/src/app/app.routing.ts @@ -1,8 +1,12 @@ import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; -const AppRoutes: Routes = [ +import { HomeRoutes } from './home/'; +import { LoginRoutes } from './login/'; +const AppRoutes: Routes = [ + ...HomeRoutes, + ...LoginRoutes ]; /** diff --git a/src/app/home/home.component.html b/src/app/home/home.component.html new file mode 100644 index 0000000..101b9f5 --- /dev/null +++ b/src/app/home/home.component.html @@ -0,0 +1,18 @@ +
+
+

Hello.

+
+
+

Good day to you {{ user }}

+

Your encoded token is:

+
+

+ {{ token }} +

+
+ +
+ +
diff --git a/src/app/home/home.component.scss b/src/app/home/home.component.scss new file mode 100644 index 0000000..70e4c9b --- /dev/null +++ b/src/app/home/home.component.scss @@ -0,0 +1,3 @@ +#wordwrap { + word-wrap: break-word; +} diff --git a/src/app/home/home.component.spec.ts b/src/app/home/home.component.spec.ts new file mode 100644 index 0000000..e7eae4d --- /dev/null +++ b/src/app/home/home.component.spec.ts @@ -0,0 +1,11 @@ +/* tslint:disable:no-unused-variable */ + +import { TestBed, async } from '@angular/core/testing'; +import { HomeComponent } from './home.component'; + +describe('Component: Home', () => { + it('should create an instance', () => { + let component = new HomeComponent(); + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/home/home.component.ts b/src/app/home/home.component.ts new file mode 100644 index 0000000..2a9c765 --- /dev/null +++ b/src/app/home/home.component.ts @@ -0,0 +1,35 @@ +import { Component, OnInit } from '@angular/core'; + +import { AuthenticationService } from '../shared/'; + +/** + * This class represents the lazy loaded HomeComponent. + */ +@Component({ + selector: 'cru-home', + templateUrl: './home.component.html', + styleUrls: ['./home.component.scss'] +}) +export class HomeComponent implements OnInit { + + currentUser: any; + user: string; + token: string; + + /** + * Creates a new LoginComponent with the injected AuthenticationService. + * @param {AuthenticationService} authenticationService - The injected AuthenticationService. + * @constructor + */ + constructor(private authenticationService: AuthenticationService) { } + + /** + * Initialises the component. + */ + ngOnInit() { + this.currentUser = JSON.parse(this.authenticationService.getCurrentUser()); + this.user = this.currentUser.username; + this.token = this.currentUser.token; + } + +} diff --git a/src/app/home/home.module.ts b/src/app/home/home.module.ts new file mode 100644 index 0000000..0f0e35e --- /dev/null +++ b/src/app/home/home.module.ts @@ -0,0 +1,12 @@ +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; + +import { SharedModule } from '../shared/shared.module'; +import { HomeComponent } from './index'; + +@NgModule({ + imports: [CommonModule, SharedModule], + declarations: [HomeComponent], + exports: [HomeComponent] +}) +export class HomeModule { } diff --git a/src/app/home/home.routing.ts b/src/app/home/home.routing.ts new file mode 100644 index 0000000..870db93 --- /dev/null +++ b/src/app/home/home.routing.ts @@ -0,0 +1,8 @@ +import { Routes } from '@angular/router'; + +import { AuthenticationGuard } from '../shared/'; +import { HomeComponent } from './home.component'; + +export const HomeRoutes: Routes = [ + { path: '', component: HomeComponent, canActivate: [AuthenticationGuard] } +]; diff --git a/src/app/home/index.ts b/src/app/home/index.ts new file mode 100644 index 0000000..b8072e7 --- /dev/null +++ b/src/app/home/index.ts @@ -0,0 +1,2 @@ +export * from './home.component'; +export * from './home.routing'; diff --git a/src/app/login/index.ts b/src/app/login/index.ts new file mode 100644 index 0000000..892f85c --- /dev/null +++ b/src/app/login/index.ts @@ -0,0 +1,2 @@ +export * from './login.component'; +export * from './login.routing'; diff --git a/src/app/login/login.component.html b/src/app/login/login.component.html new file mode 100644 index 0000000..409353a --- /dev/null +++ b/src/app/login/login.component.html @@ -0,0 +1,42 @@ +
+
+

Login.

+
+
+ +
+
+ +
+
+ +
+ +
+
+ Username is required +
+
+
+ +
+
+ +
+ +
+
+ Password is required +
+
+ +
+
+ +
diff --git a/src/app/login/login.component.scss b/src/app/login/login.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/login/login.component.spec.ts b/src/app/login/login.component.spec.ts new file mode 100644 index 0000000..d7ef9dc --- /dev/null +++ b/src/app/login/login.component.spec.ts @@ -0,0 +1,11 @@ +/* tslint:disable:no-unused-variable */ + +import { TestBed, async } from '@angular/core/testing'; +import { LoginComponent } from './login.component'; + +describe('Component: Login', () => { + it('should create an instance', () => { + let component = new LoginComponent(); + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/login/login.component.ts b/src/app/login/login.component.ts new file mode 100644 index 0000000..96d19c9 --- /dev/null +++ b/src/app/login/login.component.ts @@ -0,0 +1,52 @@ +import { Component, OnInit } from '@angular/core'; +import { Router } from '@angular/router'; + +import { AuthenticationService } from '../shared/'; + +/** + * This class represents the lazy loaded LoginComponent. + */ +@Component({ + selector: 'cru-login', + templateUrl: './login.component.html', + styleUrls: ['./login.component.scss'] +}) +export class LoginComponent implements OnInit { + + user: any = { }; + loading: boolean = false; + error: string = ''; + + /** + * Creates a new LoginComponent with the injected Router and AuthenticationService. + * @param {Router} router - The injected Router. + * @param {AuthenticationService} authenticationService - The injected AuthenticationService. + * @constructor + */ + constructor(private router: Router, private authenticationService: AuthenticationService) { } + + /** + * Initialises the component and resets the login status. + */ + ngOnInit() { + this.authenticationService.logout(); + } + + /** + * Attempts to login the user with the given credentials of the login form. + */ + login() { + this.loading = true; + this.authenticationService.login(this.user.username, this.user.password) + .subscribe(result => { + if (result === true) { + this.router.navigate(['/']); + } else { + this.error = 'Username or password is incorrect'; + this.loading = false; + } + } + ); + } + +} diff --git a/src/app/login/login.module.ts b/src/app/login/login.module.ts new file mode 100644 index 0000000..7dcec74 --- /dev/null +++ b/src/app/login/login.module.ts @@ -0,0 +1,12 @@ +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; + +import { SharedModule } from '../shared/shared.module'; +import { LoginComponent } from './index'; + +@NgModule({ + imports: [CommonModule, SharedModule], + declarations: [LoginComponent], + exports: [LoginComponent] +}) +export class LoginModule { } diff --git a/src/app/login/login.routing.ts b/src/app/login/login.routing.ts new file mode 100644 index 0000000..ab20829 --- /dev/null +++ b/src/app/login/login.routing.ts @@ -0,0 +1,7 @@ +import { Routes } from '@angular/router'; + +import { LoginComponent } from './login.component'; + +export const LoginRoutes: Routes = [ + { path: 'login', component: LoginComponent } +]; diff --git a/src/app/shared/authentication/authentication.guard.ts b/src/app/shared/authentication/authentication.guard.ts new file mode 100644 index 0000000..9a8c58c --- /dev/null +++ b/src/app/shared/authentication/authentication.guard.ts @@ -0,0 +1,32 @@ +import { Injectable } from '@angular/core'; +import { Router, CanActivate } from '@angular/router'; + +/** + * This class implements a guard for routes that require successful authentication. + */ +@Injectable() +export class AuthenticationGuard implements CanActivate { + + /** + * Creates an instance of the AuthenticationGuard class. + * @param {Router} router - The injected Router + * @constructor + */ + constructor(private router: Router) { } + + /** + * To protect routes from being accessible without previous authentication, + * the `canActivate()` method checks if the LocalStorage contains a + * `currentUser`, which equates to a user being logged in. Only then the + * navigation will pass on to the requested route. Otherwise the user will be + * redirected to the login view. + */ + canActivate() { + if (localStorage.getItem('currentUser')) { + return true; + } + this.router.navigate(['/login']); + return false; + } + +} diff --git a/src/app/shared/authentication/authentication.module.ts b/src/app/shared/authentication/authentication.module.ts new file mode 100644 index 0000000..de28f2c --- /dev/null +++ b/src/app/shared/authentication/authentication.module.ts @@ -0,0 +1,20 @@ +import { NgModule, ModuleWithProviders } from '@angular/core'; + +import { AuthenticationGuard, AuthenticationService } from './index'; + +/** + * Do not specify providers for modules that might be imported by a lazy loaded module. + */ +@NgModule({ }) +export class AuthenticationModule { + + static forRoot(): ModuleWithProviders { + return { + ngModule: AuthenticationModule, + providers: [ + AuthenticationGuard, AuthenticationService + ] + }; + } + +} diff --git a/src/app/shared/authentication/authentication.service.ts b/src/app/shared/authentication/authentication.service.ts new file mode 100644 index 0000000..765830e --- /dev/null +++ b/src/app/shared/authentication/authentication.service.ts @@ -0,0 +1,91 @@ +import { Injectable } from '@angular/core'; +import { Headers, Http, RequestOptions, Response } from '@angular/http'; +import { Observable } from 'rxjs'; +import 'rxjs/add/operator/map' + +import { environment } from '../../../environments/environment'; + +/** + * This class implements a JWT authorisation for the application. + */ +@Injectable() +export class AuthenticationService { + + token: string; + baseUrl: string; + + /** + * Creates an instance of the AuthenticationService class. + * @param {Http} http - The injected Http + * @constructor + */ + constructor(private http: Http) { + // set token if saved in local storage + const currentUser = JSON.parse(localStorage.getItem('currentUser')); + this.token = currentUser && currentUser.token; + this.baseUrl = environment.apiBaseUrl; + } + + /** + * Authorises the given credentials. An error will be thrown if the username or password is not correct. + * @param {string} username - The username + * @param {string} password - The password + * @return {boolean} `true` if the authorisation was successful, otherwise `false`. + */ + login(username: string, password: string): Observable { + return this.http.post(this.baseUrl + 'users/sign_in.json', JSON.stringify({ user: { email: username, password: password }}), this.getRequestOptions()) + .map((response: Response) => { + // login successful if there's a jwt token in the response + let token = response.json() && response.json().token; + if (token) { + // set token property + this.token = token; + + // store username and jwt token in local storage to keep user logged in between page refreshes + localStorage.setItem('currentUser', JSON.stringify({ username: username, token: token })); + + // return true to indicate successful login + return true; + } else { + // return false to indicate failed login + return false; + } + } + ); + } + + /** + * Logs out the current user by removing it from the LocalStorage. + */ + logout(): void { + this.token = null; + localStorage.removeItem('currentUser'); + } + + /** + * Returns the current users from the LocalStorage. + * @return {any} The LocalStorage item containing the current users id. + */ + getCurrentUser(): any { + return localStorage.getItem('currentUser'); + } + + /** + * Returns if there is a user currently logged in. + * @return {boolean} `true` if a user is currently logged in, otherwise `false`. + */ + isUserLoggedIn(): boolean { + return this.getCurrentUser() !== null; + } + + /** + * Returns the RequestOptions for the HTTP POST and HTTP PATCH Requests + * @return {RequestOptions} The request options. + */ + getRequestOptions(): RequestOptions { + const headers: Headers = new Headers({ 'Content-Type': 'application/json' }); + const requestOptions: RequestOptions = new RequestOptions({ headers: headers }); + return requestOptions; + } + +} diff --git a/src/app/shared/authentication/index.ts b/src/app/shared/authentication/index.ts new file mode 100644 index 0000000..ff53bf5 --- /dev/null +++ b/src/app/shared/authentication/index.ts @@ -0,0 +1,2 @@ +export * from './authentication.guard'; +export * from './authentication.service'; diff --git a/src/app/shared/index.ts b/src/app/shared/index.ts index e69de29..7d6c550 100644 --- a/src/app/shared/index.ts +++ b/src/app/shared/index.ts @@ -0,0 +1,2 @@ +export * from './authentication/'; +export * from './navigation/'; diff --git a/src/app/shared/navigation/index.ts b/src/app/shared/navigation/index.ts new file mode 100644 index 0000000..e7cdd0a --- /dev/null +++ b/src/app/shared/navigation/index.ts @@ -0,0 +1 @@ +export * from './navigation.component'; diff --git a/src/app/shared/navigation/navigation.component.html b/src/app/shared/navigation/navigation.component.html new file mode 100644 index 0000000..abb6e88 --- /dev/null +++ b/src/app/shared/navigation/navigation.component.html @@ -0,0 +1,6 @@ + diff --git a/src/app/shared/navigation/navigation.component.scss b/src/app/shared/navigation/navigation.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/shared/navigation/navigation.component.spec.ts b/src/app/shared/navigation/navigation.component.spec.ts new file mode 100644 index 0000000..e8a26a2 --- /dev/null +++ b/src/app/shared/navigation/navigation.component.spec.ts @@ -0,0 +1,11 @@ +/* tslint:disable:no-unused-variable */ + +import { TestBed, async } from '@angular/core/testing'; +import { NavigationComponent } from './navigation.component'; + +describe('Component: Navigation', () => { + it('should create an instance', () => { + let component = new NavigationComponent(); + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/shared/navigation/navigation.component.ts b/src/app/shared/navigation/navigation.component.ts new file mode 100644 index 0000000..4c0469c --- /dev/null +++ b/src/app/shared/navigation/navigation.component.ts @@ -0,0 +1,42 @@ +import { Component, OnInit } from '@angular/core'; + +import { AuthenticationService } from '../authentication/'; + +/** + * This class represents the navigation bar component. + */ +@Component({ + selector: 'cru-navigation', + templateUrl: './navigation.component.html', + styleUrls: ['./navigation.component.scss'] +}) +export class NavigationComponent implements OnInit { + + /** + * Creates a new NavigationComponent with the injected AuthenticationService. + * @param {AuthenticationService} authorisationService - The injected AuthenticationService. + * @constructor + */ + constructor(private authenticationService: AuthenticationService) { } + + ngOnInit() { + } + + /** + * Returns if a user is currently logged in. + * @return {boolean} `true` if a user is logged in, else `false`. + */ + isUserLoggedIn(): boolean { + return this.authenticationService.isUserLoggedIn(); + } + + /** + * Logs out the current user. + * @return {boolean} `false` after the service call completed. + */ + onLogoutUser(): boolean { + this.authenticationService.logout(); + return false; + } + +} diff --git a/src/app/shared/navigation/navigation.module.ts b/src/app/shared/navigation/navigation.module.ts new file mode 100644 index 0000000..ffd9782 --- /dev/null +++ b/src/app/shared/navigation/navigation.module.ts @@ -0,0 +1,14 @@ +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; +import { RouterModule } from '@angular/router'; + +import { AuthenticationModule } from '../authentication/authentication.module'; + +import { NavigationComponent } from './index'; + +@NgModule({ + imports: [CommonModule, RouterModule, AuthenticationModule.forRoot()], + declarations: [NavigationComponent], + exports: [NavigationComponent] +}) +export class NavigationModule { } diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts new file mode 100644 index 0000000..46b86ab --- /dev/null +++ b/src/app/shared/shared.module.ts @@ -0,0 +1,31 @@ +import { CommonModule } from '@angular/common'; +import { NgModule, ModuleWithProviders } from '@angular/core'; +import { FormsModule } from '@angular/forms'; +import { RouterModule } from '@angular/router'; + +import { AuthenticationModule } from './authentication/authentication.module'; +import { NavigationModule } from './navigation/navigation.module'; + +@NgModule({ + imports: [ + // @angular/common + CommonModule, + // @angular/router + RouterModule, + // authentication/authentication.module + AuthenticationModule.forRoot(), + // navigation/navigation.module + NavigationModule + ], + exports: [ + // @angular/common + CommonModule, + // @angular/forms + FormsModule, + // @angular/router + RouterModule, + // navigation/navigation.module + NavigationModule + ] +}) +export class SharedModule { } diff --git a/src/environments/environment.prod.ts b/src/environments/environment.prod.ts index 3612073..b6f12e4 100644 --- a/src/environments/environment.prod.ts +++ b/src/environments/environment.prod.ts @@ -1,3 +1,4 @@ export const environment = { - production: true + production: true, + apiBaseUrl: 'http://46.101.145.144:3000/' }; diff --git a/src/environments/environment.ts b/src/environments/environment.ts index 00313f1..c12889d 100644 --- a/src/environments/environment.ts +++ b/src/environments/environment.ts @@ -4,5 +4,6 @@ // The list of which env maps to which file can be found in `angular-cli.json`. export const environment = { - production: false + production: false, + apiBaseUrl: 'http://localhost:3000/' }; From b2073086e4c1df1a8f397b6f00a72ed367f22768 Mon Sep 17 00:00:00 2001 From: TheDonDope Date: Mon, 10 Oct 2016 21:11:44 +0200 Subject: [PATCH 10/10] chore(release): 1.0.0 --- CHANGELOG.md | 13 +++++++++++++ package.json | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..ce41948 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,13 @@ + +# 1.0.0 (2016-10-10) + + +### Features + +* **jwt:** provide login, home and shared module cb72080 +* **routing:** provide app routing module 57bc688 +* **styling:** configure bootstrap 6449ddd +* **styling:** configure font-awesome 4c496bc + + + diff --git a/package.json b/package.json index 61737d0..a465720 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "crudular", - "version": "0.0.0", + "version": "1.0.0", "license": "MIT", "angular-cli": {}, "scripts": {