<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <!-- IE required polyfills, in this exact order -->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/es6-shim/0.34.4/es6-shim.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.16/system-polyfills.js"></script>
  
  <script src="https://code.angularjs.org/tools/system.js"></script>
  <script src="https://code.angularjs.org/2.0.0-beta.16/angular2-polyfills.js"></script>
  <script src="https://code.angularjs.org/tools/typescript.js"></script>
  <script src="config.js"></script>
  <script src="https://code.angularjs.org/2.0.0-beta.16/angular2.js"></script>
  <script src="https://code.angularjs.org/2.0.0-beta.16/http.dev.js"></script>
  <script src="https://code.angularjs.org/2.0.0-beta.16/router.dev.js"></script>
  <script src="https://code.angularjs.org/2.0.0-beta.16/Rx.min.js"></script>
  <script>
    System.import('app')
      .catch(console.error.bind(console));
  </script>
</head>

<body>
  
  <app>Loading....</app>
</body>

</html>
//main entry point
import {HTTP_PROVIDERS} from 'angular2/http';
import {bootstrap} from 'angular2/platform/browser';
import {provide, ComponentRef} from 'angular2/core';
import {ROUTER_PROVIDERS} from 'angular2/router';
import {LocationStrategy, HashLocationStrategy} from 'angular2/platform/common';
import {App} from './app';
import {Auth} from './Auth';
import {appInjector} from './app-injector';
import 'rxjs/Rx';

bootstrap(App, [
  Auth,
  HTTP_PROVIDERS,
  ROUTER_PROVIDERS,
  provide(LocationStrategy, {useClass: HashLocationStrategy})
]).then((appRef: ComponentRef) => {
  // store a reference to the application injector
  appInjector(appRef.injector);
});
//our root app component
import {Component} from 'angular2/core';
import {ROUTER_DIRECTIVES, RouteConfig} from 'angular2/router';
import {Home} from './Home';
import {Login} from './Login';
import {Protected} from './Protected';
import {Parent} from './Parent';

@Component({
  selector: 'app',
  template: `
    <a [routerLink]="['/Home']">Home</a><br/>
    <a [routerLink]="['/Protected']">Protected Page</a><br/>
    <a [routerLink]="['/Parent', 'Child']">Protected Parent/Child route</a><br/>
    <a [routerLink]="['/Login']">Login</a><br/>
    <br/>
    
    <router-outlet></router-outlet>  
  `,
  directives: [ROUTER_DIRECTIVES]
})
@RouteConfig([
  {path: '/', component: Home, name: 'Home'},
  {path: '/protected', component: Protected, name: 'Protected'},
  {path: '/login', component: Login, name: 'Login'},
  {path: '/parent/...', component: Parent, name: 'Parent'}
])
export class App {
}
import {Component} from 'angular2/core';

@Component({
  selector: 'home',
  template: 'Home'
})
export class Home {

}
System.config({
  //use typescript for compilation
  transpiler: 'typescript',
  //typescript compiler options
  typescriptOptions: {
    emitDecoratorMetadata: true
  },
  //map tells the System loader where to look for things
  map: {
    app: "./src"
  },
  //packages defines our app package
  packages: {
    app: {
      main: './main.ts',
      defaultExtension: 'ts'
    }
  }
});
import {Component, View} from 'angular2/core';
import {CanActivate} from 'angular2/router';
import {Page} from './Page';
import {isLoggedIn} from './is-logged-in';

@Component({
  selector: 'protected',
  template: 'Protected'
})
@CanActivate((next: ComponentInstruction, previous: ComponentInstruction) => {
  return isLoggedIn(next, previous);
})
export class Protected {
}
import {Injector} from 'angular2/core';
import {appInjector} from './app-injector';
import {Auth} from './Auth';
import {Router, ComponentInstruction} from 'angular2/router';

export const isLoggedIn = (next: ComponentInstruction, previous: ComponentInstruction) => {
	let injector: Injector = appInjector(); // get the stored reference to the injector
	let auth: Auth = injector.get(Auth);
	let router: Router = injector.get(Router);

  // return a boolean or a promise that resolves a boolean
	return new Promise((resolve) => {
	  auth.check()
	      .subscribe((result) => {
					if (result) {
						resolve(true);
					} else {
						router.navigate(['/Login']);
						resolve(false);
					}
				});
  });
};
import {Injector} from 'angular2/core';

let appInjectorRef: Injector;
export const appInjector = (injector?: Injector):Injector => {
	if (injector) {
	  appInjectorRef = injector;
	}

	return appInjectorRef;
};
import {Observable} from 'rxjs/Observable';

export class Auth {
  constructor() {
    this.loggedIn = false;
  }
  
  login() {
    this.loggedIn = true;
  }
  
  logout() {
    this.loggedIn = false;
  }
  
  check() {
    return Observable.of(this.loggedIn);
  }
}
import {Component} from 'angular2/core';
import {Auth} from './Auth';

@Component({
  selector: 'login',
  template: `
    Logged in: {{ auth.loggedIn }}<br>
    <button (click)="login()" *ngIf="!auth.loggedIn">Login</button>
    <button (click)="logout()" *ngIf="auth.loggedIn">Logout</button>
  `
})
export class Login {
  constructor(auth: Auth) {
    this.auth = auth;
  }
  
  login() {
    this.auth.login();    
  }
  
  logout() {
    this.auth.logout();
  }
}
import {Component} from 'angular2/core';
import {RouteConfig, ROUTER_DIRECTIVES, CanActivate} from 'angular2/router';
import {Child} from './Child';
import {isLoggedIn} from './is-logged-in';

@Component({
  selector: 'parent',
  template: `
    The parent route is protected by CanActivate
    <br><br>
    <router-outlet></router-outlet>
  `,
  directives: [ROUTER_DIRECTIVES]
})
@RouteConfig([
  {path: '/', component: Child, name: 'Child'}
])
@CanActivate((next: ComponentInstruction, previous: ComponentInstruction) => {
  return isLoggedIn(next, previous);
})
export class Parent {
  
}
import {Component} from 'angular2/core';

@Component({
  selector: 'child',
  template: `
    The child route is protected because the parent route is protected by CanActivate
  `
})
export class Child {
  
}