├── .gitignore
├── client
├── src
│ ├── assets
│ │ └── .gitkeep
│ ├── app
│ │ ├── note-detail
│ │ │ ├── note-detail.component.css
│ │ │ ├── note-detail.component.spec.ts
│ │ │ ├── note-detail.component.html
│ │ │ └── note-detail.component.ts
│ │ ├── login
│ │ │ ├── login.component.html
│ │ │ ├── login.component.css
│ │ │ ├── login.component.spec.ts
│ │ │ └── login.component.ts
│ │ ├── shared
│ │ │ ├── okta
│ │ │ │ ├── index.ts
│ │ │ │ ├── okta.guard.ts
│ │ │ │ ├── okta.interceptor.ts
│ │ │ │ └── okta.service.ts
│ │ │ └── note
│ │ │ │ ├── note.service.spec.ts
│ │ │ │ └── note.service.ts
│ │ ├── app.component.css
│ │ ├── note-list
│ │ │ ├── note-list.component.css
│ │ │ ├── note-list.component.ts
│ │ │ ├── note-list.component.html
│ │ │ └── note-list.component.spec.ts
│ │ ├── app.component.html
│ │ ├── app.component.ts
│ │ ├── app.component.spec.ts
│ │ └── app.module.ts
│ ├── environments
│ │ ├── environment.prod.ts
│ │ └── environment.ts
│ ├── favicon.ico
│ ├── typings.d.ts
│ ├── tsconfig.app.json
│ ├── index.html
│ ├── main.ts
│ ├── tsconfig.spec.json
│ ├── styles.css
│ ├── test.ts
│ └── polyfills.ts
├── e2e
│ ├── app.po.ts
│ ├── tsconfig.e2e.json
│ └── app.e2e-spec.ts
├── .editorconfig
├── tsconfig.json
├── .gitignore
├── protractor.conf.js
├── karma.conf.js
├── README.md
├── .angular-cli.json
├── package.json
└── tslint.json
├── reset.sh
├── server
├── .mvn
│ └── wrapper
│ │ ├── maven-wrapper.jar
│ │ └── maven-wrapper.properties
├── src
│ ├── main
│ │ ├── resources
│ │ │ └── application.properties
│ │ └── kotlin
│ │ │ └── com
│ │ │ └── okta
│ │ │ └── developer
│ │ │ └── notes
│ │ │ └── NotesApplication.kt
│ └── test
│ │ └── kotlin
│ │ └── com
│ │ └── okta
│ │ └── developer
│ │ └── notes
│ │ └── NotesApplicationTests.kt
├── .gitignore
├── mvnw.cmd
├── pom.xml
└── mvnw
├── manifest.yml
├── .idea
└── misc.xml
├── README.md
└── LICENSE
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 |
--------------------------------------------------------------------------------
/client/src/assets/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/client/src/app/note-detail/note-detail.component.css:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/client/src/app/login/login.component.html:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/client/src/environments/environment.prod.ts:
--------------------------------------------------------------------------------
1 | export const environment = {
2 | production: true
3 | };
4 |
--------------------------------------------------------------------------------
/reset.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | cf d -f notes-server
4 | cf d -f notes-client
5 |
6 | cf delete-orphaned-routes
7 |
--------------------------------------------------------------------------------
/client/src/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oktadev/okta-kotlin-typescript-notes-example/HEAD/client/src/favicon.ico
--------------------------------------------------------------------------------
/client/src/app/shared/okta/index.ts:
--------------------------------------------------------------------------------
1 | export * from './okta.service';
2 | export * from './okta.guard';
3 | export * from './okta.interceptor';
4 |
--------------------------------------------------------------------------------
/client/src/typings.d.ts:
--------------------------------------------------------------------------------
1 | /* SystemJS module definition */
2 | declare var module: NodeModule;
3 | interface NodeModule {
4 | id: string;
5 | }
6 |
--------------------------------------------------------------------------------
/server/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oktadev/okta-kotlin-typescript-notes-example/HEAD/server/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/server/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.0/apache-maven-3.5.0-bin.zip
2 |
--------------------------------------------------------------------------------
/server/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | okta.oauth.issuer=https://dev-158606.oktapreview.com/oauth2/default
2 | okta.oauth.clientId=0oabl213xlbMjGJYo0h7
--------------------------------------------------------------------------------
/client/src/app/app.component.css:
--------------------------------------------------------------------------------
1 | mat-toolbar a {
2 | color: rgba(255, 255, 255, .87);
3 | text-decoration: none;
4 | }
5 |
6 | .fill-remaining-space {
7 | flex: 1 1 auto;
8 | }
9 |
--------------------------------------------------------------------------------
/client/src/app/note-list/note-list.component.css:
--------------------------------------------------------------------------------
1 | :host {
2 | padding-left: 5px;
3 | display: block;
4 | }
5 |
6 | .btn-add {
7 | margin-left: 10px;
8 | margin-top: 10px;
9 | }
10 |
11 | .link {
12 | cursor: pointer;
13 | }
14 |
--------------------------------------------------------------------------------
/client/e2e/app.po.ts:
--------------------------------------------------------------------------------
1 | import { browser, by, element } from 'protractor';
2 |
3 | export class AppPage {
4 | navigateTo() {
5 | return browser.get('/');
6 | }
7 |
8 | getParagraphText() {
9 | return element(by.css('app-root h1')).getText();
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/client/src/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../out-tsc/app",
5 | "baseUrl": "./",
6 | "module": "es2015",
7 | "types": []
8 | },
9 | "exclude": [
10 | "test.ts",
11 | "**/*.spec.ts"
12 | ]
13 | }
14 |
--------------------------------------------------------------------------------
/client/src/app/login/login.component.css:
--------------------------------------------------------------------------------
1 | #okta-signin-container {
2 | margin-top: 25px;
3 | }
4 |
5 | @media only screen
6 | and (min-device-width: 414px)
7 | and (max-device-width: 736px)
8 | and (-webkit-min-device-pixel-ratio: 3) {
9 | #okta-signin-container {
10 | margin-top: 0;
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/client/.editorconfig:
--------------------------------------------------------------------------------
1 | # Editor configuration, see http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | charset = utf-8
6 | indent_style = space
7 | indent_size = 2
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
11 | [*.md]
12 | max_line_length = off
13 | trim_trailing_whitespace = false
14 |
--------------------------------------------------------------------------------
/manifest.yml:
--------------------------------------------------------------------------------
1 | ---
2 | applications:
3 |
4 | - name: notes-server
5 | host: notes-by-kotlin
6 | path: ./server/target/notes-0.0.1-SNAPSHOT.jar
7 | env :
8 | FORCE_HTTPS: true
9 |
10 | - name: notes-client
11 | host: notes-with-typescript
12 | path: ./client/dist/
13 | env :
14 | FORCE_HTTPS: true
15 |
--------------------------------------------------------------------------------
/client/e2e/tsconfig.e2e.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../out-tsc/e2e",
5 | "baseUrl": "./",
6 | "module": "commonjs",
7 | "target": "es5",
8 | "types": [
9 | "jasmine",
10 | "jasminewd2",
11 | "node"
12 | ]
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/server/.gitignore:
--------------------------------------------------------------------------------
1 | target/
2 | !.mvn/wrapper/maven-wrapper.jar
3 |
4 | ### STS ###
5 | .apt_generated
6 | .classpath
7 | .factorypath
8 | .project
9 | .settings
10 | .springBeans
11 |
12 | ### IntelliJ IDEA ###
13 | .idea
14 | *.iws
15 | *.iml
16 | *.ipr
17 |
18 | ### NetBeans ###
19 | nbproject/private/
20 | build/
21 | nbbuild/
22 | dist/
23 | nbdist/
24 | .nb-gradle/
--------------------------------------------------------------------------------
/client/e2e/app.e2e-spec.ts:
--------------------------------------------------------------------------------
1 | import { AppPage } from './app.po';
2 |
3 | describe('notes App', () => {
4 | let page: AppPage;
5 |
6 | beforeEach(() => {
7 | page = new AppPage();
8 | });
9 |
10 | it('should display welcome message', () => {
11 | page.navigateTo();
12 | expect(page.getParagraphText()).toEqual('Welcome to app!');
13 | });
14 | });
15 |
--------------------------------------------------------------------------------
/client/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Notes
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/client/src/app/app.component.html:
--------------------------------------------------------------------------------
1 |
2 | {{title}}
3 |
4 |
5 | Welcome {{user?.name}}!
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/client/src/main.ts:
--------------------------------------------------------------------------------
1 | import { enableProdMode } from '@angular/core';
2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
3 |
4 | import { AppModule } from './app/app.module';
5 | import { environment } from './environments/environment';
6 |
7 | if (environment.production) {
8 | enableProdMode();
9 | }
10 |
11 | platformBrowserDynamic().bootstrapModule(AppModule);
12 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/client/src/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../out-tsc/spec",
5 | "baseUrl": "./",
6 | "module": "commonjs",
7 | "target": "es5",
8 | "types": [
9 | "jasmine",
10 | "node"
11 | ]
12 | },
13 | "files": [
14 | "test.ts"
15 | ],
16 | "include": [
17 | "**/*.spec.ts",
18 | "**/*.d.ts"
19 | ]
20 | }
21 |
--------------------------------------------------------------------------------
/client/src/environments/environment.ts:
--------------------------------------------------------------------------------
1 | // The file contents for the current environment will overwrite these during build.
2 | // The build system defaults to the dev environment which uses `environment.ts`, but if you do
3 | // `ng build --env=prod` then `environment.prod.ts` will be used instead.
4 | // The list of which env maps to which file can be found in `.angular-cli.json`.
5 |
6 | export const environment = {
7 | production: false
8 | };
9 |
--------------------------------------------------------------------------------
/client/src/styles.css:
--------------------------------------------------------------------------------
1 | @import '~@okta/okta-signin-widget/dist/css/okta-sign-in.min.css';
2 | @import '~@okta/okta-signin-widget/dist/css/okta-theme.css';
3 | @import "~@angular/material/prebuilt-themes/indigo-pink.css";
4 | @import '~https://fonts.googleapis.com/icon?family=Material+Icons';
5 |
6 | body {
7 | margin: 0;
8 | font-family: Roboto, sans-serif;
9 | }
10 |
11 | #okta-sign-in.auth-container {
12 | font-family: Roboto, sans-serif;
13 | }
14 |
--------------------------------------------------------------------------------
/client/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compileOnSave": false,
3 | "compilerOptions": {
4 | "outDir": "./dist/out-tsc",
5 | "sourceMap": true,
6 | "declaration": false,
7 | "moduleResolution": "node",
8 | "emitDecoratorMetadata": true,
9 | "experimentalDecorators": true,
10 | "target": "es5",
11 | "typeRoots": [
12 | "node_modules/@types"
13 | ],
14 | "lib": [
15 | "es2017",
16 | "dom"
17 | ]
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/client/src/app/shared/note/note.service.spec.ts:
--------------------------------------------------------------------------------
1 | import { TestBed, inject } from '@angular/core/testing';
2 |
3 | import { NoteService } from './note.service';
4 |
5 | describe('NoteService', () => {
6 | beforeEach(() => {
7 | TestBed.configureTestingModule({
8 | providers: [NoteService]
9 | });
10 | });
11 |
12 | it('should be created', inject([NoteService], (service: NoteService) => {
13 | expect(service).toBeTruthy();
14 | }));
15 | });
16 |
--------------------------------------------------------------------------------
/client/src/app/note-list/note-list.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 | import { NoteService } from '../shared/note/note.service';
3 |
4 | @Component({
5 | selector: 'app-note-list',
6 | templateUrl: './note-list.component.html',
7 | styleUrls: ['./note-list.component.css']
8 | })
9 | export class NoteListComponent implements OnInit {
10 | notes: Array;
11 |
12 | constructor(private noteService: NoteService) {
13 | }
14 |
15 | ngOnInit() {
16 | this.noteService.getAll().subscribe(data => {
17 | this.notes = data;
18 | }, error => console.error(error));
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/client/src/app/note-list/note-list.component.html:
--------------------------------------------------------------------------------
1 |
2 | Notes List
3 |
4 |
5 |
7 | {{note.text}}
8 |
9 |
10 | No notes found.
11 |
12 |
13 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/client/src/app/app.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 | import { OktaAuthService } from './shared/okta/okta.service';
3 |
4 | @Component({
5 | selector: 'app-root',
6 | templateUrl: './app.component.html',
7 | styleUrls: ['./app.component.css']
8 | })
9 | export class AppComponent implements OnInit {
10 | title = 'My Notes';
11 | user;
12 |
13 | constructor(public oktaService: OktaAuthService) {
14 | }
15 |
16 | ngOnInit() {
17 | if (this.oktaService.isAuthenticated()) {
18 | this.user = this.oktaService.idTokenAsUser;
19 | }
20 |
21 | this.oktaService.user$.subscribe(user => {
22 | this.user = user;
23 | });
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/client/src/app/shared/okta/okta.guard.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 | import { ActivatedRouteSnapshot, CanActivate, RouterStateSnapshot } from '@angular/router';
3 | import { OktaAuthService } from './okta.service';
4 |
5 | @Injectable()
6 | export class OktaAuthGuard implements CanActivate {
7 | signIn;
8 | authenticated;
9 |
10 | constructor(private oktaService: OktaAuthService) {
11 | this.signIn = oktaService;
12 | }
13 |
14 | canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
15 | this.authenticated = this.oktaService.isAuthenticated();
16 | if (this.authenticated) {
17 | return true;
18 | }
19 | this.signIn.login();
20 | return false;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/client/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # compiled output
4 | /dist
5 | /tmp
6 | /out-tsc
7 |
8 | # dependencies
9 | /node_modules
10 |
11 | # IDEs and editors
12 | /.idea
13 | .project
14 | .classpath
15 | .c9/
16 | *.launch
17 | .settings/
18 | *.sublime-workspace
19 |
20 | # IDE - VSCode
21 | .vscode/*
22 | !.vscode/settings.json
23 | !.vscode/tasks.json
24 | !.vscode/launch.json
25 | !.vscode/extensions.json
26 |
27 | # misc
28 | /.sass-cache
29 | /connect.lock
30 | /coverage
31 | /libpeerconnection.log
32 | npm-debug.log
33 | testem.log
34 | /typings
35 | yarn-error.log
36 |
37 | # e2e
38 | /e2e/*.js
39 | /e2e/*.map
40 |
41 | # System Files
42 | .DS_Store
43 | Thumbs.db
44 |
--------------------------------------------------------------------------------
/client/src/app/login/login.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing';
2 |
3 | import { LoginComponent } from './login.component';
4 |
5 | describe('LoginComponent', () => {
6 | let component: LoginComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(async(() => {
10 | TestBed.configureTestingModule({
11 | declarations: [ LoginComponent ]
12 | })
13 | .compileComponents();
14 | }));
15 |
16 | beforeEach(() => {
17 | fixture = TestBed.createComponent(LoginComponent);
18 | component = fixture.componentInstance;
19 | fixture.detectChanges();
20 | });
21 |
22 | it('should be created', () => {
23 | expect(component).toBeTruthy();
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/client/src/app/note-list/note-list.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing';
2 |
3 | import { NoteListComponent } from './note-list.component';
4 |
5 | describe('NoteListComponent', () => {
6 | let component: NoteListComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(async(() => {
10 | TestBed.configureTestingModule({
11 | declarations: [ NoteListComponent ]
12 | })
13 | .compileComponents();
14 | }));
15 |
16 | beforeEach(() => {
17 | fixture = TestBed.createComponent(NoteListComponent);
18 | component = fixture.componentInstance;
19 | fixture.detectChanges();
20 | });
21 |
22 | it('should be created', () => {
23 | expect(component).toBeTruthy();
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/client/src/app/note-detail/note-detail.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing';
2 |
3 | import { NoteDetailComponent } from './note-detail.component';
4 |
5 | describe('NoteDetailComponent', () => {
6 | let component: NoteDetailComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(async(() => {
10 | TestBed.configureTestingModule({
11 | declarations: [ NoteDetailComponent ]
12 | })
13 | .compileComponents();
14 | }));
15 |
16 | beforeEach(() => {
17 | fixture = TestBed.createComponent(NoteDetailComponent);
18 | component = fixture.componentInstance;
19 | fixture.detectChanges();
20 | });
21 |
22 | it('should be created', () => {
23 | expect(component).toBeTruthy();
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/client/protractor.conf.js:
--------------------------------------------------------------------------------
1 | // Protractor configuration file, see link for more information
2 | // https://github.com/angular/protractor/blob/master/lib/config.ts
3 |
4 | const { SpecReporter } = require('jasmine-spec-reporter');
5 |
6 | exports.config = {
7 | allScriptsTimeout: 11000,
8 | specs: [
9 | './e2e/**/*.e2e-spec.ts'
10 | ],
11 | capabilities: {
12 | 'browserName': 'chrome'
13 | },
14 | directConnect: true,
15 | baseUrl: 'http://localhost:4200/',
16 | framework: 'jasmine',
17 | jasmineNodeOpts: {
18 | showColors: true,
19 | defaultTimeoutInterval: 30000,
20 | print: function() {}
21 | },
22 | onPrepare() {
23 | require('ts-node').register({
24 | project: 'e2e/tsconfig.e2e.json'
25 | });
26 | jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
27 | }
28 | };
29 |
--------------------------------------------------------------------------------
/client/src/app/login/login.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 | import { OktaAuthService } from '../shared/okta/okta.service';
3 | import { Router } from '@angular/router';
4 |
5 | @Component({
6 | selector: 'app-login',
7 | templateUrl: './login.component.html',
8 | styleUrls: ['./login.component.css']
9 | })
10 | export class LoginComponent implements OnInit {
11 |
12 | constructor(private oktaService: OktaAuthService,
13 | private router: Router) {
14 | }
15 |
16 | ngOnInit() {
17 | if (this.oktaService.isAuthenticated()) {
18 | this.router.navigate(['/']);
19 | } else {
20 | this.oktaService.showLogin();
21 | }
22 |
23 | // user authentication listener
24 | this.oktaService.user$.subscribe(user => {
25 | this.router.navigate(['/']);
26 | });
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/client/karma.conf.js:
--------------------------------------------------------------------------------
1 | // Karma configuration file, see link for more information
2 | // https://karma-runner.github.io/1.0/config/configuration-file.html
3 |
4 | module.exports = function (config) {
5 | config.set({
6 | basePath: '',
7 | frameworks: ['jasmine', '@angular/cli'],
8 | plugins: [
9 | require('karma-jasmine'),
10 | require('karma-chrome-launcher'),
11 | require('karma-jasmine-html-reporter'),
12 | require('karma-coverage-istanbul-reporter'),
13 | require('@angular/cli/plugins/karma')
14 | ],
15 | client:{
16 | clearContext: false // leave Jasmine Spec Runner output visible in browser
17 | },
18 | coverageIstanbulReporter: {
19 | reports: [ 'html', 'lcovonly' ],
20 | fixWebpackSourcePaths: true
21 | },
22 | angularCli: {
23 | environment: 'dev'
24 | },
25 | reporters: ['progress', 'kjhtml'],
26 | port: 9876,
27 | colors: true,
28 | logLevel: config.LOG_INFO,
29 | autoWatch: true,
30 | browsers: ['Chrome'],
31 | singleRun: false
32 | });
33 | };
34 |
--------------------------------------------------------------------------------
/client/src/app/note-detail/note-detail.component.html:
--------------------------------------------------------------------------------
1 |
26 |
--------------------------------------------------------------------------------
/client/src/app/shared/note/note.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 | import { Response } from '@angular/http';
3 | import { Observable } from 'rxjs/Observable';
4 | import 'rxjs/add/operator/map';
5 | import 'rxjs/add/operator/catch';
6 | import { HttpClient } from '@angular/common/http';
7 |
8 | @Injectable()
9 | export class NoteService {
10 | public API = 'http://localhost:8080';
11 | public NOTE_API = this.API + '/notes';
12 |
13 | constructor(private http: HttpClient) {
14 | }
15 |
16 | getAll(): Observable {
17 | return this.http.get(this.API);
18 | }
19 |
20 | get(id: string) {
21 | return this.http.get(this.NOTE_API + '/' + id);
22 | }
23 |
24 | save(note: any): Observable {
25 | let result: Observable