├── LICENSE
├── README.md
├── css
└── bike.css
├── html
├── admin.component.html
├── home.component.html
└── view-registration.component.html
├── java
└── SecurityConfiguration.java
├── js
└── auth.service.ts
├── node
├── README.md
└── server.js
├── proxy
└── proxy.conf.json
└── sql
├── bike.db
└── bike.sql
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Dan Bunker
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ps-spring-boot-and-angular
--------------------------------------------------------------------------------
/css/bike.css:
--------------------------------------------------------------------------------
1 | html {
2 | height: 100%;
3 | }
4 |
5 | body {
6 | padding-top: 10px;
7 | padding-bottom: 10px;
8 | text-rendering: optimizeLegibility;
9 | position: relative;
10 | min-height: 100%;
11 | -webkit-font-smoothing: antialiased;
12 | -moz-osx-font-smoothing: grayscale;
13 | font-family: 'Courier New', sans-serif;
14 | font-weight: normal;
15 | font-size: 1.5em;
16 | background: linear-gradient(150deg,#D5E3F1 15%,#FFFBD9 70%,#FFDFCB 94%);
17 | }
18 |
19 | h1 {
20 | font-size: 2.0em;
21 | }
22 |
23 | .table-bordered, .table-bordered td, .table-bordered th {
24 | border: 1px solid #2F465D;
25 | }
26 |
--------------------------------------------------------------------------------
/html/admin.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Owner Name |
5 | Email |
6 | Model |
7 | Purchase Price |
8 |
9 |
10 |
11 | {{bike.name}}
12 | |
13 |
14 | {{bike.email}}
15 | |
16 |
17 | {{bike.model}}
18 | |
19 |
20 | {{bike.purchasePrice}}
21 | |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/html/home.component.html:
--------------------------------------------------------------------------------
1 |
44 |
--------------------------------------------------------------------------------
/html/view-registration.component.html:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
10 |
14 |
18 |
22 |
26 |
30 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/java/SecurityConfiguration.java:
--------------------------------------------------------------------------------
1 | package com.globomatics.bike.config;
2 |
3 | import org.springframework.beans.factory.annotation.Value;
4 | import org.springframework.context.annotation.Configuration;
5 | import org.springframework.http.HttpMethod;
6 | import org.springframework.security.config.annotation.web.builders.HttpSecurity;
7 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
8 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
9 |
10 | import com.auth0.spring.security.api.JwtWebSecurityConfigurer;
11 |
12 | @EnableWebSecurity
13 | @Configuration
14 | public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
15 | @Value(value = "${auth0.apiAudience}")
16 | private String apiAudience;
17 | @Value(value = "${auth0.issuer}")
18 | private String issuer;
19 |
20 | @Override
21 | protected void configure(HttpSecurity http) throws Exception {
22 | JwtWebSecurityConfigurer
23 | .forRS256(apiAudience, issuer)
24 | .configure(http)
25 | .authorizeRequests()
26 | .antMatchers(HttpMethod.POST, "/api/v1/bikes").permitAll()
27 | .antMatchers(HttpMethod.GET, "/api/v1/bikes").hasAuthority("view:registrations")
28 | .antMatchers(HttpMethod.GET, "/api/v1/bikes/**").hasAuthority("view:registration")
29 | .anyRequest().authenticated();
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/js/auth.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 | import { Router } from '@angular/router';
3 | import 'rxjs/add/operator/filter';
4 | import * as auth0 from 'auth0-js';
5 |
6 | @Injectable()
7 | export class AuthService {
8 |
9 | auth0 = new auth0.WebAuth({
10 | clientID: '',
11 | domain: '',
12 | responseType: 'token id_token',
13 | audience: 'http://localhost:8080',
14 | redirectUri: 'http://localhost:4200/callback',
15 | scope: 'openid view:registration view:registrations'
16 | });
17 |
18 | constructor(public router: Router) {}
19 |
20 | public login(): void {
21 | this.auth0.authorize();
22 | }
23 |
24 | public handleAuthentication(): void {
25 | this.auth0.parseHash((err, authResult) => {
26 | if (authResult && authResult.accessToken && authResult.idToken) {
27 | window.location.hash = '';
28 | this.setSession(authResult);
29 | this.router.navigate(['/admin']);
30 | } else if (err) {
31 | this.router.navigate(['/admin']);
32 | console.log(err);
33 | }
34 | });
35 | }
36 |
37 | private setSession(authResult): void {
38 | // Set the time that the access token will expire at
39 | const expiresAt = JSON.stringify((authResult.expiresIn * 1000) + new Date().getTime());
40 | localStorage.setItem('access_token', authResult.accessToken);
41 | localStorage.setItem('id_token', authResult.idToken);
42 | localStorage.setItem('expires_at', expiresAt);
43 | }
44 |
45 | public logout(): void {
46 | // Remove tokens and expiry time from localStorage
47 | localStorage.removeItem('access_token');
48 | localStorage.removeItem('id_token');
49 | localStorage.removeItem('expires_at');
50 | // Go back to the home route
51 | this.router.navigate(['/']);
52 | }
53 |
54 | public isAuthenticated(): boolean {
55 | // Check whether the current time is past the
56 | // access token's expiry time
57 | const expiresAt = JSON.parse(localStorage.getItem('expires_at'));
58 | return new Date().getTime() < expiresAt;
59 | }
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/node/README.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dlbunker/ps-spring-boot-and-angular/3ab9d01470a2a97a6920465efb575c2e0d02935c/node/README.md
--------------------------------------------------------------------------------
/node/server.js:
--------------------------------------------------------------------------------
1 | // Get dependencies
2 | const express = require('express');
3 | const path = require('path');
4 | const http = require('http');
5 | const bodyParser = require('body-parser');
6 | const proxy = require('express-http-proxy');
7 | const cors = require('cors');
8 |
9 | const app = express();
10 |
11 | // Parsers for POST data
12 | app.use(bodyParser.json({limit: '20mb'}));
13 | app.use(bodyParser.urlencoded({ extended: false, limit: '20mb' }));
14 |
15 | app.use(cors());
16 |
17 | // Point static path to dist
18 | app.use(express.static(path.join(__dirname, 'dist')));
19 |
20 | // Set our api routes proxy to point to spring boot server
21 | app.use('/server', proxy('http://localhost:8080'));
22 |
23 | // Catch all other routes and return the index file
24 | app.get('*', (req, res) => {
25 | res.sendFile(path.join(__dirname, 'dist/index.html'));
26 | });
27 |
28 | /**
29 | * Get port from environment and store in Express.
30 | */
31 | const port = '4200';
32 | app.set('port', port);
33 |
34 | /**
35 | * Create HTTP server.
36 | */
37 | const server = http.createServer(app);
38 |
39 | /**
40 | * Listen on provided port, on all network interfaces.
41 | */
42 | server.listen(port, () => console.log(`API running on ${port}`));
43 |
--------------------------------------------------------------------------------
/proxy/proxy.conf.json:
--------------------------------------------------------------------------------
1 | {
2 | "/server": {
3 | "target": "http://localhost:8080",
4 | "secure": false,
5 | "changeOrigin": true,
6 | "logLevel": "debug",
7 | "pathRewrite": {
8 | "^/server" : ""
9 | }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/sql/bike.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dlbunker/ps-spring-boot-and-angular/3ab9d01470a2a97a6920465efb575c2e0d02935c/sql/bike.db
--------------------------------------------------------------------------------
/sql/bike.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE
2 | bike
3 | (
4 | id BIGINT NOT NULL,
5 | contact BOOLEAN NOT NULL,
6 | email VARCHAR,
7 | model VARCHAR,
8 | name VARCHAR,
9 | phone VARCHAR,
10 | purchase_date DATETIME,
11 | purchase_price NUMERIC,
12 | serial_number VARCHAR,
13 | PRIMARY KEY (id)
14 | );
15 |
16 | CREATE TABLE
17 | hibernate_sequence
18 | (
19 | next_val BIGINT
20 | );
21 |
22 | INSERT INTO bike (id, contact, email, model, name, phone, purchase_date, purchase_price)
23 | VALUES (1, 1, 'jeff@bikes.com', 'Globo MTB 29 Full Suspension', 'Jeff Miller', '328-443-5555', 4419619200000, '1100');
24 | INSERT INTO bike (id, contact, email, model, name, phone, purchase_date, purchase_price)
25 | VALUES (2, 0, 'samantha@bikes.com', 'Globo Carbon Fiber Race Series', 'Samantha Davis', '448-397-5555', 4419619200000, '1999');
26 | INSERT INTO bike (id, contact, email, model, name, phone, purchase_date, purchase_price)
27 | VALUES (3, 1, 'dave@bikes.com', 'Globo Time Trial Blade', 'Dave Warren', '563-891-5555', 4419619200000, '2100');
28 |
29 | INSERT INTO hibernate_sequence (next_val) VALUES (4);
30 |
--------------------------------------------------------------------------------