Browse Source

Implement Login

Carsten Porth 5 years ago
parent
commit
62c89816bb

+ 4 - 0
app/README.md

@@ -0,0 +1,4 @@
+# How to run the app
+
+Run on Android emulator: `ionic cordova emulate android`
+Run in Browser: `ionic lab` or `ionic serve`

+ 2 - 0
app/config.xml

@@ -81,4 +81,6 @@
     <plugin name="cordova-plugin-splashscreen" spec="5.0.2" />
     <plugin name="cordova-plugin-ionic-webview" spec="1.1.19" />
     <plugin name="cordova-plugin-ionic-keyboard" spec="2.0.5" />
+    <plugin name="cordova-plugin-secure-storage" spec="^2.6.8" />
+    <engine name="android" spec="~7.0.0" />
 </widget>

+ 27 - 2
app/package.json

@@ -22,9 +22,21 @@
     "@angular/platform-browser": "5.2.11",
     "@angular/platform-browser-dynamic": "5.2.11",
     "@ionic-native/core": "4.8.0",
+    "@ionic-native/secure-storage": "^4.9.0",
     "@ionic-native/splash-screen": "4.8.0",
     "@ionic-native/status-bar": "4.8.0",
     "@ionic/storage": "2.1.3",
+    "cordova-android": "~7.0.0",
+    "cordova-plugin-device": "^2.0.2",
+    "cordova-plugin-ionic-keyboard": "^2.0.5",
+    "cordova-plugin-ionic-webview": "^1.1.19",
+    "cordova-plugin-secure-storage": "^2.6.8",
+    "cordova-plugin-splashscreen": "^5.0.2",
+    "cordova-plugin-whitelist": "^1.3.3",
+    "cordova-support-android-plugin": "^1.0.1",
+    "cordova-support-google-services": "^1.2.0",
+    "crypto-js": "^3.1.9-1",
+    "firebase": "^5.2.0",
     "ionic-angular": "3.9.2",
     "ionicons": "3.0.0",
     "rxjs": "5.5.11",
@@ -35,5 +47,18 @@
     "@ionic/app-scripts": "3.1.10",
     "typescript": "~2.6.2"
   },
-  "description": "An Ionic project"
-}
+  "description": "An Ionic project",
+  "cordova": {
+    "plugins": {
+      "cordova-plugin-secure-storage": {},
+      "cordova-plugin-whitelist": {},
+      "cordova-plugin-device": {},
+      "cordova-plugin-splashscreen": {},
+      "cordova-plugin-ionic-webview": {},
+      "cordova-plugin-ionic-keyboard": {}
+    },
+    "platforms": [
+      "android"
+    ]
+  }
+}

+ 13 - 2
app/src/app/app.component.ts

@@ -3,9 +3,12 @@ import { Nav, Platform } from 'ionic-angular';
 import { StatusBar } from '@ionic-native/status-bar';
 import { SplashScreen } from '@ionic-native/splash-screen';
 
+import { AuthProvider } from '../providers/auth/auth';
+
 import { HomePage } from '../pages/home/home';
 import { SearchPage } from '../pages/search/search';
 import { SettingsPage } from '../pages/settings/settings';
+import { LoginPage } from '../pages/login/login';
 
 @Component({
   templateUrl: 'app.html'
@@ -13,16 +16,24 @@ import { SettingsPage } from '../pages/settings/settings';
 export class MyApp {
   @ViewChild(Nav) nav: Nav;
 
-  rootPage: any = HomePage;
+  rootPage: any;
 
   pages: Array<{ title: string, icon: string, component: any }>;
 
-  constructor(platform: Platform, statusBar: StatusBar, splashScreen: SplashScreen) {
+  constructor(
+    platform: Platform,
+    statusBar: StatusBar,
+    splashScreen: SplashScreen,
+    authProvider: AuthProvider
+  ) {
     platform.ready().then(() => {
       // Okay, so the platform is ready and our plugins are available.
       // Here you can do any higher level native things you might need.
+      //this.setHomepage();
+
       statusBar.styleDefault();
       splashScreen.hide();
+      this.rootPage = authProvider.isLoggedIn() ? LoginPage : HomePage;      
     });
 
     this.pages = [

+ 1 - 1
app/src/app/app.html

@@ -1,4 +1,4 @@
-<ion-menu [content]="content">
+<ion-menu id="sideNav" [content]="content">
   <ion-header>
     <ion-toolbar>
       <ion-title>Menu</ion-title>

+ 17 - 4
app/src/app/app.module.ts

@@ -3,34 +3,47 @@ import { ErrorHandler, NgModule } from '@angular/core';
 import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular';
 import { SplashScreen } from '@ionic-native/splash-screen';
 import { StatusBar } from '@ionic-native/status-bar';
+import { HttpClient, HttpClientModule } from '@angular/common/http';
+import { IonicStorageModule } from '@ionic/storage';
+
+import { AuthProvider } from '../providers/auth/auth';
 
 import { MyApp } from './app.component';
 import { HomePage } from '../pages/home/home';
 import { SearchPage } from '../pages/search/search';
 import { SettingsPage } from '../pages/settings/settings';
+import { LoginPage } from '../pages/login/login';
+import { TwitterApiProvider } from '../providers/twitter-api/twitter-api';
 
 @NgModule({
   declarations: [
     MyApp,
     HomePage,
     SearchPage,
-    SettingsPage
+    SettingsPage,
+    LoginPage
   ],
   imports: [
     BrowserModule,
-    IonicModule.forRoot(MyApp)
+    HttpClientModule,
+    IonicModule.forRoot(MyApp),
+    IonicStorageModule.forRoot()
   ],
   bootstrap: [IonicApp],
   entryComponents: [
     MyApp,
     HomePage,
     SearchPage,
-    SettingsPage
+    SettingsPage,
+    LoginPage
   ],
   providers: [
     StatusBar,
     SplashScreen,
-    { provide: ErrorHandler, useClass: IonicErrorHandler }
+    HttpClient,
+    { provide: ErrorHandler, useClass: IonicErrorHandler },
+    AuthProvider,
+    TwitterApiProvider
   ]
 })
 export class AppModule { }

+ 1 - 0
app/src/pages/home/home.html

@@ -8,6 +8,7 @@
 </ion-header>
 
 <ion-content padding>
+  <button ion-button block (click)="clickmich()">rrrrequest :D</button>
   The world is your oyster.
   <p>
     If you get lost, the

+ 12 - 2
app/src/pages/home/home.ts

@@ -1,14 +1,24 @@
 import { Component } from '@angular/core';
-import { NavController } from 'ionic-angular';
+import { NavController, MenuController } from 'ionic-angular';
+import { TwitterApiProvider } from '../../providers/twitter-api/twitter-api';
 
 @Component({
   selector: 'page-home',
   templateUrl: 'home.html'
 })
 export class HomePage {
+  menuController: MenuController;
 
-  constructor(public navCtrl: NavController) {
+  constructor(public navCtrl: NavController, private twitter: TwitterApiProvider, menuCtrl: MenuController) {
+    this.menuController = menuCtrl;
+  }
 
+  ionViewDidLoad() {
+    console.log('hi from homepage');
+    this.menuController.enable(true, 'sideNav');
   }
 
+  clickmich() {
+    this.twitter.fetchHomeFeed().subscribe(data => console.log(data));
+  }
 }

+ 18 - 0
app/src/pages/login/login.html

@@ -0,0 +1,18 @@
+<!--
+  Generated template for the LoginPage page.
+
+  See http://ionicframework.com/docs/components/#navigation for more info on
+  Ionic pages and navigation.
+-->
+<ion-header>
+
+  <ion-navbar>
+    <ion-title>Login</ion-title>
+  </ion-navbar>
+
+</ion-header>
+
+
+<ion-content padding>
+  <button ion-button outline block (click)="login()">Login</button>
+</ion-content>

+ 13 - 0
app/src/pages/login/login.module.ts

@@ -0,0 +1,13 @@
+import { NgModule } from '@angular/core';
+import { IonicPageModule } from 'ionic-angular';
+import { LoginPage } from './login';
+
+@NgModule({
+  declarations: [
+    LoginPage,
+  ],
+  imports: [
+    IonicPageModule.forChild(LoginPage),
+  ],
+})
+export class LoginPageModule {}

+ 3 - 0
app/src/pages/login/login.scss

@@ -0,0 +1,3 @@
+page-login {
+
+}

+ 39 - 0
app/src/pages/login/login.ts

@@ -0,0 +1,39 @@
+import { Component } from '@angular/core';
+import { IonicPage, NavController, NavParams, MenuController } from 'ionic-angular';
+import { AuthProvider } from '../../providers/auth/auth';
+import { HomePage } from '../home/home';
+
+/**
+ * Generated class for the LoginPage page.
+ *
+ * See https://ionicframework.com/docs/components/#navigation for more info on
+ * Ionic pages and navigation.
+ */
+
+@IonicPage()
+@Component({
+  selector: 'page-login',
+  templateUrl: 'login.html',
+})
+export class LoginPage {
+  menuController: MenuController;
+
+  constructor(public navCtrl: NavController, public navParams: NavParams, private menuCtrl: MenuController, private authProvider: AuthProvider) {
+    this.menuController = menuCtrl;
+  }
+
+  ionViewDidLoad() {
+    console.log('ionViewDidLoad LoginPage');
+    this.menuController.enable(false, 'sideNav');
+  }
+
+  login() {
+    if (this.authProvider.login()) {
+      console.log('log in successful');
+      this.navCtrl.push(HomePage);
+    } else {
+      console.log('ERROR - not logged in');
+    }
+  }
+
+}

+ 52 - 0
app/src/providers/auth/auth.ts

@@ -0,0 +1,52 @@
+import { HttpClient } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+import { Storage } from '@ionic/storage';
+import firebase from "firebase";
+
+@Injectable()
+export class AuthProvider {
+  authProvider: any;
+
+  constructor(public http: HttpClient, private storage: Storage) {
+    console.log('Hello AuthProvider Provider');
+
+    var config = {
+      apiKey: "AIzaSyCMYjjtPPZak7wBBnh9sy8Yr3Fz1145MuM",
+      authDomain: "hybridosn.firebaseapp.com",
+      databaseURL: "https://hybridosn.firebaseio.com",
+      storageBucket: "hybridosn.appspot.com",
+    };
+    firebase.initializeApp(config);
+
+    this.authProvider = new firebase.auth.TwitterAuthProvider();
+    this.authProvider.setCustomParameters({
+      'lang': 'de'
+    });
+  }
+
+  isLoggedIn() {
+    Promise.all([this.storage.get('accessTokenKey'), this.storage.get('accessTokenSecret')])
+      .then(values => {
+        console.log("looged in: " + (values[0] != null && values[1] != null));
+        return values[0] != null && values[1] != null;
+      });
+  }
+
+  login() {
+    return firebase.auth().signInWithPopup(this.authProvider)
+      .then(result => {
+        this.storage.set('accessTokenKey', result.credential["accessToken"]);
+        this.storage.set('accessTokenSecret', result.credential["secret"]);
+        return true;
+      })
+      .catch(error => {
+        console.log(error);
+        return false;
+      })
+  }
+
+  logout() {
+    this.storage.clear();
+  }
+
+}

+ 69 - 0
app/src/providers/twitter-api/twitter-api.ts

@@ -0,0 +1,69 @@
+import { Injectable } from '@angular/core';
+import { HttpClient, HttpHeaders } from '@angular/common/http';
+import { Storage } from '@ionic/storage';
+import CryptoJS from 'crypto-js';
+
+
+@Injectable()
+export class TwitterApiProvider {
+  consumer_key: string = 'UxZkbKotkr8Uc6seupnaZ1kDE';
+  consumer_secret: string = 'fEAas8iugR60FOEXsFG0iajq6oyfIIXRBVMlTgWxBd1stWIKHq';
+  access_token_key: string;
+  access_token_secret: string;
+  client;
+
+  constructor(public http: HttpClient, private storage: Storage) {
+    console.log('Hello TwitterApiProvider Provider');
+
+    Promise.all([this.storage.get('accessTokenKey'), this.storage.get('accessTokenSecret')]).then(values => {
+      this.access_token_key = values[0];
+      this.access_token_secret = values[1];
+      this.initApi();
+    });
+  }
+
+
+  initApi() {
+
+  }
+
+  private buildHeaders(): HttpHeaders {
+    let oauth_consumer_key = this.consumer_key;
+    let oauth_nonce = this.getNonce();
+    let oauth_signature = this.getSignature('get', 'https://api.twitter.com/1.1/statuses/home_timeline.json', '');
+    let oauth_signature_method = 'HMAC-SHA1';
+    let oauth_timestamp = Math.floor(Date.now() / 1000).toString();
+    let oauth_token = this.access_token_key;
+    let oauth_version = '1.0';
+
+    let authToken = `OAuth oauth_consumer_key="${oauth_consumer_key}", oauth_nonce="${oauth_nonce}", oauth_signature="${oauth_signature}", oauth_signature_method="${oauth_signature_method}", oauth_timestamp="${oauth_timestamp}", oauth_token="${oauth_token}", oauth_version="${oauth_version}"`;
+    console.log(authToken);
+
+    return new HttpHeaders({
+      'Authorization': authToken
+    });
+  }
+
+  private getNonce(numChars = 32): string {
+    var st = "0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz";
+    var l = st.length;
+    var result = "";
+
+    for (var i = 0; i < numChars; i++) {
+      var randomIndex = Math.floor(Math.random() * l);
+      result = result + st.charAt(randomIndex);
+    }
+    return result;
+  }
+
+  private getSignature(method: string, url: string, parameterString: string): string {
+    let shaKey = encodeURIComponent(this.consumer_secret) + "&" + encodeURIComponent(this.access_token_secret);
+    let signatureBaseString = `${method.toUpperCase()}&${encodeURIComponent(url)}&${encodeURIComponent(parameterString)}`;
+    let signature = CryptoJS.HmacSHA1(signatureBaseString, shaKey);
+    return CryptoJS.enc.Base64.stringify(signature);
+  }
+
+  fetchHomeFeed() {
+    return this.http.get('https://api.twitter.com/1.1/statuses/home_timeline.json', { headers: this.buildHeaders() });
+  }
+}