You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@helix.apache.org by jx...@apache.org on 2018/08/18 00:20:10 UTC

[10/14] helix git commit: add ldap support

add ldap support


Project: http://git-wip-us.apache.org/repos/asf/helix/repo
Commit: http://git-wip-us.apache.org/repos/asf/helix/commit/d60d51b2
Tree: http://git-wip-us.apache.org/repos/asf/helix/tree/d60d51b2
Diff: http://git-wip-us.apache.org/repos/asf/helix/diff/d60d51b2

Branch: refs/heads/master
Commit: d60d51b24c20b73a9b3fba906674479f4fba17e0
Parents: e94b82a
Author: Vivo Xu <vx...@linkedin.com>
Authored: Fri Mar 9 15:18:01 2018 -0800
Committer: Vivo Xu <vx...@linkedin.com>
Committed: Wed Aug 8 15:39:33 2018 -0700

----------------------------------------------------------------------
 helix-front/client/app/app.component.html       |  2 +-
 helix-front/client/app/app.component.ts         | 41 +++++++++++++++++++-
 helix-front/client/app/core/user.service.ts     | 10 +++++
 .../input-dialog/input-dialog.component.html    | 14 +++++--
 helix-front/package.json                        |  1 +
 helix-front/server/config.ts                    |  6 +++
 helix-front/server/controllers/user.ts          | 36 ++++++++++++++++-
 7 files changed, 104 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/helix/blob/d60d51b2/helix-front/client/app/app.component.html
----------------------------------------------------------------------
diff --git a/helix-front/client/app/app.component.html b/helix-front/client/app/app.component.html
index d30b162..b199228 100644
--- a/helix-front/client/app/app.component.html
+++ b/helix-front/client/app/app.component.html
@@ -5,7 +5,7 @@
       <span class="helix-title">Helix</span>
     </a>
     <span fxFlex="1 1 auto"></span>
-    <a mat-button>
+    <a mat-button (click)="login()">
       <mat-icon>person</mat-icon>
       {{ currentUser | async }}
     </a>

http://git-wip-us.apache.org/repos/asf/helix/blob/d60d51b2/helix-front/client/app/app.component.ts
----------------------------------------------------------------------
diff --git a/helix-front/client/app/app.component.ts b/helix-front/client/app/app.component.ts
index 31de982..13d7426 100644
--- a/helix-front/client/app/app.component.ts
+++ b/helix-front/client/app/app.component.ts
@@ -7,11 +7,14 @@ import {
   NavigationCancel,
   NavigationError
 } from '@angular/router';
+import { MatDialog } from '@angular/material';
 
 import { Angulartics2Piwik } from 'angulartics2';
 
 import { environment } from '../environments/environment';
 import { UserService } from './core/user.service';
+import { InputDialogComponent } from './shared/dialog/input-dialog/input-dialog.component';
+import { HelperService } from './shared/helper.service';
 
 @Component({
   selector: 'hi-root',
@@ -30,7 +33,9 @@ export class AppComponent implements OnInit {
     protected route: ActivatedRoute,
     protected router: Router,
     protected angulartics: Angulartics2Piwik,
-    protected service: UserService
+    protected dialog: MatDialog,
+    protected service: UserService,
+    protected helper: HelperService
   ) {
     router.events.subscribe(event => {
       if (event instanceof NavigationStart) {
@@ -57,4 +62,38 @@ export class AppComponent implements OnInit {
       }
     });
   }
+
+  login() {
+    this.dialog
+      .open(InputDialogComponent, {
+        data: {
+          title: 'Login',
+          message: 'Please enter your LDAP username and password to continue:',
+          values: {
+            username: {
+              label: 'Username'
+            },
+            password: {
+              label: 'Password',
+              type: 'password'
+            }
+          }
+        }
+      })
+      .afterClosed()
+      .subscribe(result => {
+        if (result && result.username.value && result.password.value) {
+          this.service
+            .login(result.username.value, result.password.value)
+            .subscribe(
+              isAuthroized => {
+                if (isAuthroized) {
+                  location.reload();
+                }
+              },
+              error => this.helper.showError(error)
+            );
+        }
+      });
+  }
 }

http://git-wip-us.apache.org/repos/asf/helix/blob/d60d51b2/helix-front/client/app/core/user.service.ts
----------------------------------------------------------------------
diff --git a/helix-front/client/app/core/user.service.ts b/helix-front/client/app/core/user.service.ts
index 3336c1f..21676af 100644
--- a/helix-front/client/app/core/user.service.ts
+++ b/helix-front/client/app/core/user.service.ts
@@ -20,6 +20,16 @@ export class UserService {
       .catch(_ => _);
   }
 
+  public login(username: string, password: string): Observable<boolean> {
+    return this.http
+      .post(
+        `${ Settings.userAPI }/login`,
+        { username: username, password: password },
+        { headers: this.getHeaders() }
+      )
+      .map(response => response.json());
+  }
+
   protected getHeaders() {
     let headers = new Headers();
     headers.append('Accept', 'application/json');

http://git-wip-us.apache.org/repos/asf/helix/blob/d60d51b2/helix-front/client/app/shared/dialog/input-dialog/input-dialog.component.html
----------------------------------------------------------------------
diff --git a/helix-front/client/app/shared/dialog/input-dialog/input-dialog.component.html b/helix-front/client/app/shared/dialog/input-dialog/input-dialog.component.html
index bf4cd78..153dda3 100644
--- a/helix-front/client/app/shared/dialog/input-dialog/input-dialog.component.html
+++ b/helix-front/client/app/shared/dialog/input-dialog/input-dialog.component.html
@@ -4,8 +4,8 @@
     <section>
       {{ message }}
     </section>
-    <section *ngFor="let name of getKeys(values)">
-      <section *ngIf="values[name].type === 'boolean'">
+    <section *ngFor="let name of getKeys(values)" [ngSwitch]="values[name].type">
+      <section *ngSwitchCase="'boolean'">
         {{ values[name].label }}:
         <mat-slide-toggle
           [name]="name"
@@ -13,7 +13,15 @@
           {{ values[name].value ? 'True' : 'False' }}
         </mat-slide-toggle>
       </section>
-      <mat-form-field *ngIf="values[name].type !== 'boolean'">
+      <mat-form-field *ngSwitchCase="'password'">
+        <input matInput
+          type="password"
+          [name]="name"
+          [(ngModel)]="values[name].value"
+          [placeholder]="values[name].label"
+          required>
+      </mat-form-field>
+      <mat-form-field *ngSwitchDefault>
         <input matInput
           [name]="name"
           [(ngModel)]="values[name].value"

http://git-wip-us.apache.org/repos/asf/helix/blob/d60d51b2/helix-front/package.json
----------------------------------------------------------------------
diff --git a/helix-front/package.json b/helix-front/package.json
index 846ff78..844980b 100644
--- a/helix-front/package.json
+++ b/helix-front/package.json
@@ -44,6 +44,7 @@
     "express": "^4.15.3",
     "express-session": "^1.15.6",
     "hammerjs": "^2.0.8",
+    "ldap-client": "^3.1.3",
     "lodash": "^4.17.4",
     "moment": "^2.22.2",
     "morgan": "^1.8.2",

http://git-wip-us.apache.org/repos/asf/helix/blob/d60d51b2/helix-front/server/config.ts
----------------------------------------------------------------------
diff --git a/helix-front/server/config.ts b/helix-front/server/config.ts
index 1f49dd2..1a4265b 100644
--- a/helix-front/server/config.ts
+++ b/helix-front/server/config.ts
@@ -14,6 +14,12 @@ export const SSL = {
   cafiles: []
 };
 
+export const LDAP = {
+  uri: 'ldap://example.com',
+  base: 'DC=example,DC=com',
+  principalSuffix: '@example.com'
+};
+
 export function CheckAdmin(username: string, callback: (boolean) => void) {
   callback(username === 'root');
 }

http://git-wip-us.apache.org/repos/asf/helix/blob/d60d51b2/helix-front/server/controllers/user.ts
----------------------------------------------------------------------
diff --git a/helix-front/server/controllers/user.ts b/helix-front/server/controllers/user.ts
index 84d2c11..609b9f8 100644
--- a/helix-front/server/controllers/user.ts
+++ b/helix-front/server/controllers/user.ts
@@ -1,13 +1,15 @@
 import { Request, Response, Router } from 'express';
 
 import * as request from 'request';
+import * as LdapClient from 'ldap-client';
 
-import { CheckAdmin } from '../config';
+import { LDAP, CheckAdmin } from '../config';
 
 export class UserCtrl {
 
   constructor(router: Router) {
     router.route('/user/authorize').get(this.authorize);
+    router.route('/user/login').post(this.login.bind(this));
     router.route('/user/current').get(this.current);
     router.route('/user/can').get(this.can);
   }
@@ -37,4 +39,36 @@ export class UserCtrl {
   protected can(req: Request, res: Response) {
     res.json(req.session.isAdmin ? true : false);
   }
+
+  protected login(req: Request, res: Response) {
+    const credential = req.body;
+    if (!credential.username || !credential.password) {
+      res.status(401).json(false);
+      return;
+    }
+
+    // check LDAP
+    const ldap = new LdapClient({ uri: LDAP.uri, base: LDAP.base }, err => {
+      if (err) {
+        res.status(500).json(err);
+      }
+    });
+
+    ldap.bind({
+      binddn: credential.username + LDAP.principalSuffix,
+      password: credential.password
+    }, err => {
+      if (err) {
+        res.status(401).json(false);
+      } else {
+        // authroized
+        req.session.username = credential.username;
+        CheckAdmin(req.session.username, (isAdmin: boolean) => {
+          req.session.isAdmin = isAdmin;
+          res.json(true);
+        });
+      }
+    });
+  }
+
 }