Authored by 姜枫

add login

@@ -11,7 +11,7 @@ import mount from 'koa-mount'; @@ -11,7 +11,7 @@ import mount from 'koa-mount';
11 import serve from 'koa-static'; 11 import serve from 'koa-static';
12 import body from './middleware/yoho-koa-body'; 12 import body from './middleware/yoho-koa-body';
13 import convert from 'koa-convert'; 13 import convert from 'koa-convert';
14 - 14 +import session from 'koa-session';
15 import Socket from 'socket.io'; 15 import Socket from 'socket.io';
16 16
17 import config from './config/config'; 17 import config from './config/config';
@@ -26,7 +26,9 @@ const server = http.createServer(app.callback()); @@ -26,7 +26,9 @@ const server = http.createServer(app.callback());
26 const io = new Socket(server); 26 const io = new Socket(server);
27 ws.init(io); 27 ws.init(io);
28 28
  29 +app.keys = ['yoho-node-ci secret'];
29 app.use(serve(__dirname + '/public')); 30 app.use(serve(__dirname + '/public'));
  31 +app.use(convert(session({}, app)));
30 app.use(convert(body({ 32 app.use(convert(body({
31 multipart: true, 33 multipart: true,
32 queryString: { 34 queryString: {
1 -'use strict';  
2 -  
3 -import Router from 'koa-router';  
4 -  
5 -import * as models from '../../models';  
6 -  
7 -let r = new Router();  
8 -  
9 -r.get('/init', async(ctx, next) => {  
10 - let clean = Object.keys(models).map(k => {  
11 - let db = models[k];  
12 - return db.remove({});  
13 - });  
14 -  
15 - await Promise.all(clean);  
16 -  
17 - let seeds = [];  
18 -  
19 - Object.keys(models).forEach(k => {  
20 - let db = models[k];  
21 - let ss = db._seeds();  
22 - ss.forEach(s => {  
23 - seeds.push(db.insert(s));  
24 - });  
25 - });  
26 -  
27 - await Promise.all(seeds);  
28 - ctx.body = 'success';  
29 -});  
30 -  
31 -r.get('/test', async(ctx, next) => {  
32 - console.log('test');  
33 - ctx.body = await ctx.render('test', {  
34 - name: 'yoho'  
35 - });  
36 -});  
37 -  
38 -export default r;  
  1 +'use strict';
  2 +
  3 +import Router from 'koa-router';
  4 +
  5 +let r = new Router();
  6 +
  7 +const login = {
  8 + loginPage: async (ctx, next) => {
  9 + await ctx.render('login', { layout: '' });
  10 + },
  11 + auth: async (ctx, next) => {
  12 + let username = ctx.request.body.username;
  13 + let password = ctx.request.body.password;
  14 +
  15 + if (username === 'yoho' && password === 'yoho9646') {
  16 + ctx.session = {
  17 + user: 'yoho'
  18 + };
  19 + ctx.redirect('/projects');
  20 + ctx.status = 301;
  21 + } else {
  22 + ctx.flash = { error: '账户密码错误' };
  23 + await ctx.render('login', { layout: '', message: ctx.flash.error });
  24 + }
  25 + },
  26 + logout: (ctx, next) => {
  27 + ctx.session = null;
  28 + ctx.redirect('/');
  29 + ctx.status = 301;
  30 + }
  31 +};
  32 +
  33 +r.get('/login', login.loginPage);
  34 +r.get('/logout', login.logout);
  35 +r.post('/auth', login.auth);
  36 +
  37 +
  38 +export default r;
@@ -5,6 +5,8 @@ import moment from 'moment'; @@ -5,6 +5,8 @@ import moment from 'moment';
5 import Build from '../../ci/build'; 5 import Build from '../../ci/build';
6 import Deploy from '../../ci/deploy'; 6 import Deploy from '../../ci/deploy';
7 7
  8 +import ws from '../../../lib/ws';
  9 +
8 import { 10 import {
9 Building, 11 Building,
10 Project, 12 Project,
@@ -7,6 +7,8 @@ import { @@ -7,6 +7,8 @@ import {
7 } from '../../models'; 7 } from '../../models';
8 8
9 9
  10 +
  11 +
10 const r = new Router; 12 const r = new Router;
11 13
12 const envs = { 14 const envs = {
@@ -7,6 +7,7 @@ @@ -7,6 +7,7 @@
7 import path from 'path'; 7 import path from 'path';
8 import Koa from 'koa'; 8 import Koa from 'koa';
9 import convert from 'koa-convert'; 9 import convert from 'koa-convert';
  10 +
10 import hbs from '../../middleware/yoho-koa-hbs'; 11 import hbs from '../../middleware/yoho-koa-hbs';
11 import helpers from '../../lib/helpers'; 12 import helpers from '../../lib/helpers';
12 import routers from './routers' 13 import routers from './routers'
@@ -3,17 +3,29 @@ import Router from 'koa-router'; @@ -3,17 +3,29 @@ import Router from 'koa-router';
3 import index from './actions/index'; 3 import index from './actions/index';
4 import projects from './actions/projects'; 4 import projects from './actions/projects';
5 import servers from './actions/servers'; 5 import servers from './actions/servers';
6 -import init from './actions/init';  
7 - 6 +import login from './actions/login';
8 7
  8 +const noAuth = new Router();
9 const base = new Router(); 9 const base = new Router();
10 10
11 -export default function(app) { 11 +export default function (app) {
  12 +
  13 + noAuth.use('', login.routes(), login.allowedMethods());
  14 + app.use(noAuth.routes(), noAuth.allowedMethods());
  15 + app.use(async (ctx, next) => {
  16 +
  17 + if (ctx.session && ctx.session.user) {
  18 + await next();
  19 + } else {
  20 + ctx.redirect('/login');
  21 + }
  22 + });
  23 +
12 base.use('/projects', projects.routes(), projects.allowedMethods()); 24 base.use('/projects', projects.routes(), projects.allowedMethods());
13 base.use('/servers', servers.routes(), servers.allowedMethods()); 25 base.use('/servers', servers.routes(), servers.allowedMethods());
14 26
15 base.use('', index.routes(), index.allowedMethods()); 27 base.use('', index.routes(), index.allowedMethods());
16 - base.use('', init.routes(), init.allowedMethods());  
17 28
18 app.use(base.routes(), base.allowedMethods()); 29 app.use(base.routes(), base.allowedMethods());
  30 +
19 } 31 }
@@ -20,7 +20,7 @@ @@ -20,7 +20,7 @@
20 <div class="panel-heading"> 20 <div class="panel-heading">
21 <div class="pull-right"> 21 <div class="pull-right">
22 <a class="btn btn-info btn-rounded mr5 log-btn"><i class="fa fa-eye"></i> 查看构建日志</a> 22 <a class="btn btn-info btn-rounded mr5 log-btn"><i class="fa fa-eye"></i> 查看构建日志</a>
23 - <a class="btn btn-warning btn-rounded mr5 rollback-btn"><i class="fa fa-reply"></i> 回滚</a> 23 + {{!--<a class="btn btn-warning btn-rounded mr5 rollback-btn"><i class="fa fa-reply"></i> 回滚</a>--}}
24 <a class="btn btn-success btn-rounded mr20 build-btn"><i class="glyphicon glyphicon-plus"></i> 新增构建</a> 24 <a class="btn btn-success btn-rounded mr20 build-btn"><i class="glyphicon glyphicon-plus"></i> 新增构建</a>
25 <a href="" class="tooltips panel-minimize"><i class="fa fa-minus"></i></a> 25 <a href="" class="tooltips panel-minimize"><i class="fa fa-minus"></i></a>
26 </div> 26 </div>
  1 +<!DOCTYPE html>
  2 +<html lang="en">
  3 + <head>
  4 + <meta charset="utf-8">
  5 + <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
  6 + <meta name="description" content="">
  7 + <meta name="author" content="">
  8 +
  9 + <title>{{title}}</title>
  10 +
  11 + <link href="css/style.default.css" rel="stylesheet">
  12 +
  13 + <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
  14 + <!--[if lt IE 9]>
  15 + <script src="js/html5shiv.js"></script>
  16 + <script src="js/respond.min.js"></script>
  17 + <![endif]-->
  18 + </head>
  19 +
  20 + <body class="signin">
  21 + <section>
  22 +
  23 + <div class="panel panel-signin">
  24 + <div class="panel-body">
  25 + <div class="logo text-center">
  26 + <img src="images/logo.png" alt="yoho!" >
  27 + </div>
  28 + <br />
  29 +
  30 + <p class="text-center">{{message}}</p>
  31 + <div class="mb30"></div>
  32 +
  33 + <form action="/auth" method="post">
  34 + <div class="input-group mb15">
  35 + <span class="input-group-addon"><i class="glyphicon glyphicon-user"></i></span>
  36 + <input type="text" class="form-control" placeholder="Username" name="username">
  37 + </div><!-- input-group -->
  38 + <div class="input-group mb15">
  39 + <span class="input-group-addon"><i class="glyphicon glyphicon-lock"></i></span>
  40 + <input type="password" class="form-control" placeholder="Password" name="password">
  41 + </div><!-- input-group -->
  42 +
  43 + <div class="clearfix">
  44 + {{!--<div class="pull-left">
  45 + <div class="ckbox ckbox-primary mt10">
  46 + <input type="checkbox" id="rememberMe" value="1">
  47 + <label for="rememberMe">Remember Me</label>
  48 + </div>
  49 + </div>--}}
  50 + <div class="pull-right">
  51 + <button type="submit" class="btn btn-success">Sign In <i class="fa fa-angle-right ml5"></i></button>
  52 + </div>
  53 + </div>
  54 + </form>
  55 +
  56 + </div><!-- panel-body -->
  57 + </div><!-- panel -->
  58 +
  59 + </section>
  60 +
  61 +
  62 + <script src="js/jquery-1.11.1.min.js"></script>
  63 + <script src="js/jquery-migrate-1.2.1.min.js"></script>
  64 + <script src="js/bootstrap.min.js"></script>
  65 + <script src="js/modernizr.min.js"></script>
  66 + <script src="js/pace.min.js"></script>
  67 + <script src="js/retina.min.js"></script>
  68 + <script src="js/jquery.cookies.js"></script>
  69 +
  70 + <script src="js/custom.js"></script>
  71 +
  72 + </body>
  73 +</html>
@@ -16,7 +16,7 @@ @@ -16,7 +16,7 @@
16 16
17 <div class="pull-right"> 17 <div class="pull-right">
18 18
19 - <form class="form form-search" action="search-results.html"> 19 + {{!--<form class="form form-search" action="search-results.html">
20 <input type="search" class="form-control" placeholder="Search" /> 20 <input type="search" class="form-control" placeholder="Search" />
21 </form> 21 </form>
22 22
@@ -131,20 +131,20 @@ @@ -131,20 +131,20 @@
131 </div> 131 </div>
132 <!-- dropdown-menu --> 132 <!-- dropdown-menu -->
133 </div> 133 </div>
134 - <!-- btn-group --> 134 + <!-- btn-group -->--}}
135 135
136 - <div class="btn-group btn-group-option">  
137 - <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">  
138 - <i class="fa fa-caret-down"></i> 136 + <div class="btn-group">
  137 + <button id="logout" type="button" class="btn btn-default">
  138 + <i class="glyphicon glyphicon-log-out"></i> 退出
139 </button> 139 </button>
140 - <ul class="dropdown-menu pull-right" role="menu"> 140 + {{!--<ul class="dropdown-menu pull-right" role="menu">
141 <li><a href="#"><i class="glyphicon glyphicon-user"></i> My Profile</a></li> 141 <li><a href="#"><i class="glyphicon glyphicon-user"></i> My Profile</a></li>
142 <li><a href="#"><i class="glyphicon glyphicon-star"></i> Activity Log</a></li> 142 <li><a href="#"><i class="glyphicon glyphicon-star"></i> Activity Log</a></li>
143 <li><a href="#"><i class="glyphicon glyphicon-cog"></i> Account Settings</a></li> 143 <li><a href="#"><i class="glyphicon glyphicon-cog"></i> Account Settings</a></li>
144 <li><a href="#"><i class="glyphicon glyphicon-question-sign"></i> Help</a></li> 144 <li><a href="#"><i class="glyphicon glyphicon-question-sign"></i> Help</a></li>
145 <li class="divider"></li> 145 <li class="divider"></li>
146 <li><a href="#"><i class="glyphicon glyphicon-log-out"></i>Sign Out</a></li> 146 <li><a href="#"><i class="glyphicon glyphicon-log-out"></i>Sign Out</a></li>
147 - </ul> 147 + </ul>--}}
148 </div> 148 </div>
149 <!-- btn-group --> 149 <!-- btn-group -->
150 150
@@ -16,7 +16,6 @@ @@ -16,7 +16,6 @@
16 <li><a href="/projects"><i class="glyphicon glyphicon-th"></i> <span>Projects</span></a></li> 16 <li><a href="/projects"><i class="glyphicon glyphicon-th"></i> <span>Projects</span></a></li>
17 <li class="parent"><a href=""><i class="fa fa-gears"></i> <span>Settings</span></a> 17 <li class="parent"><a href=""><i class="fa fa-gears"></i> <span>Settings</span></a>
18 <ul class="children"> 18 <ul class="children">
19 - <li><a href="/test">Test</a></li>  
20 <li><a href="/servers/setting">Servers</a></li> 19 <li><a href="/servers/setting">Servers</a></li>
21 </ul> 20 </ul>
22 </li> 21 </li>
@@ -9,14 +9,21 @@ class Ws { @@ -9,14 +9,21 @@ class Ws {
9 init(io) { 9 init(io) {
10 this.io = io; 10 this.io = io;
11 this.io.on('connection', this.onConn); 11 this.io.on('connection', this.onConn);
  12 + this.io.of('/building/log', this.onBuildingLogConn);
12 } 13 }
13 14
14 broadcast(path, msg) { 15 broadcast(path, msg) {
15 this.io.emit(path, msg); 16 this.io.emit(path, msg);
16 } 17 }
17 18
18 - onConn(ws) { 19 + onConn(socket) {
  20 + console.log(socket.conn.id);
  21 + }
19 22
  23 + onBuildingLogConn(socket) {
  24 + socket.on('message', (msg) => {
  25 + console.log(msg);
  26 + });
20 } 27 }
21 } 28 }
22 29
@@ -32,6 +32,7 @@ @@ -32,6 +32,7 @@
32 "author": "jiangfeng <jeff.jiang@yoho.cn>", 32 "author": "jiangfeng <jeff.jiang@yoho.cn>",
33 "license": "ISC", 33 "license": "ISC",
34 "dependencies": { 34 "dependencies": {
  35 + "co": "^4.6.0",
35 "co-body": "^4.2.0", 36 "co-body": "^4.2.0",
36 "formidable": "^1.0.17", 37 "formidable": "^1.0.17",
37 "fs-promise": "^0.5.0", 38 "fs-promise": "^0.5.0",
@@ -42,6 +43,7 @@ @@ -42,6 +43,7 @@
42 "koa-convert": "^1.2.0", 43 "koa-convert": "^1.2.0",
43 "koa-mount": "^2.0.0", 44 "koa-mount": "^2.0.0",
44 "koa-router": "^7.0.1", 45 "koa-router": "^7.0.1",
  46 + "koa-session": "^3.3.1",
45 "koa-static": "^3.0.0", 47 "koa-static": "^3.0.0",
46 "lodash": "^4.13.1", 48 "lodash": "^4.13.1",
47 "moment": "^2.13.0", 49 "moment": "^2.13.0",
@@ -98,6 +98,10 @@ jQuery(document).ready(function() { @@ -98,6 +98,10 @@ jQuery(document).ready(function() {
98 } 98 }
99 } 99 }
100 100
  101 + jQuery('#logout').click(function(){
  102 + location.href = '/logout';
  103 + });
  104 +
101 }); 105 });
102 106
103 107