浏览代码

reorg and logon handler

bmallred 9 年之前
父节点
当前提交
ddc9ef4599
共有 16 个文件被更改,包括 257 次插入315 次删除
  1. 6 2
      account.go
  2. 7 5
      account_test.go
  3. 3 3
      environment.go
  4. 1 1
      environment_test.go
  5. 26 0
      handlers/logon.go
  6. 1 1
      html/article.html
  7. 6 13
      html/blog.html
  8. 179 259
      html/default.html
  9. 6 13
      html/loop.html
  10. 2 2
      html/workspace.html
  11. 二进制
      loop
  12. 8 8
      main.go
  13. 1 1
      markdown.go
  14. 1 1
      markdown_test.go
  15. 6 4
      security.go
  16. 4 2
      security_test.go

+ 6 - 2
account.go

@ -1,4 +1,4 @@
1
package main
1
package account
2 2
3 3
import (
4 4
	"encoding/json"
@ -9,9 +9,13 @@ import (
9 9
	"path/filepath"
10 10
	"strings"
11 11
	"time"
12
13
	"code.revolvingcow.com/revolvingcow/loop/environment"
14
	"code.revolvingcow.com/revolvingcow/loop/security"
12 15
)
13 16
14 17
const (
18
	UserFile          = "loop_users"
15 19
	publishDateLayout = "200601021504"
16 20
)
17 21
@ -200,7 +204,7 @@ func (a *Account) Add(content, filename string, file []byte) (string, error) {
200 204
201 205
	// Create new content directory if necessary
202 206
	if content == "" {
203
		content = fmt.Sprintf("%x", hash(userDir+time.Now().Format(publishDateLayout), salt()))
207
		content = fmt.Sprintf("%x", security.Hash(userDir+time.Now().Format(publishDateLayout), environment.Salt()))
204 208
	}
205 209
206 210
	// Create new content directory

+ 7 - 5
account_test.go

@ -1,9 +1,11 @@
1
package main
1
package account
2 2
3 3
import (
4 4
	"os"
5 5
	"testing"
6 6
	"time"
7
8
	"code.revolvingcow.com/revolvingcow/loop/environment"
7 9
)
8 10
9 11
func TestGetAccounts(t *testing.T) {
@ -19,7 +21,7 @@ func TestCreate(t *testing.T) {
19 21
		Passphrase: "guest",
20 22
	}
21 23
22
	ConfigureEnvironment()
24
	environment.ConfigureEnvironment()
23 25
	err := a.Create()
24 26
	if err != nil {
25 27
		t.Error(err)
@ -55,7 +57,7 @@ func TestAdd(t *testing.T) {
55 57
		Passphrase: "guest",
56 58
	}
57 59
58
	ConfigureEnvironment()
60
	environment.ConfigureEnvironment()
59 61
	fp, err := a.Add("", "", []byte{})
60 62
	if err == nil {
61 63
		t.Error("Fake content should not be publishable")
@ -76,7 +78,7 @@ func TestPublish(t *testing.T) {
76 78
		Passphrase: "guest",
77 79
	}
78 80
79
	ConfigureEnvironment()
81
	environment.ConfigureEnvironment()
80 82
	err := a.Publish("My first blog post", "thisshouldnotexist", time.Now())
81 83
	if err == nil {
82 84
		t.Error("Fake content should not be publishable")
@ -89,7 +91,7 @@ func TestDelete(t *testing.T) {
89 91
		Passphrase: "guest",
90 92
	}
91 93
92
	ConfigureEnvironment()
94
	environment.ConfigureEnvironment()
93 95
	err := a.Delete()
94 96
	if err != nil {
95 97
		t.Error(err)

+ 3 - 3
environment.go

@ -1,4 +1,4 @@
1
package main
1
package environment
2 2
3 3
import "os"
4 4
@ -19,10 +19,10 @@ func ConfigureEnvironment() {
19 19
	}
20 20
}
21 21
22
func address() string {
22
func Address() string {
23 23
	return os.Getenv("LOOP_URL")
24 24
}
25 25
26
func salt() string {
26
func Salt() string {
27 27
	return os.Getenv("LOOP_SALT")
28 28
}

+ 1 - 1
environment_test.go

@ -1,4 +1,4 @@
1
package main
1
package environment
2 2
3 3
import (
4 4
	"os"

+ 26 - 0
handlers/logon.go

@ -0,0 +1,26 @@
1
package handlers
2
3
import (
4
	"net/http"
5
6
	"code.revolvingcow.com/revolvingcow/loop/account"
7
)
8
9
func LogonHandler(w http.ResponseWriter, r *http.Request) {
10
	email := r.FormValue("email")
11
	password := r.FormValue("password")
12
	a := account.Account{
13
		Username:   email,
14
		Passphrase: password,
15
	}
16
17
	err := a.Create()
18
	if err != nil {
19
		if err.Error() == "Account already exists" {
20
			http.Error(w, err.Error(), http.StatusInternalServerError)
21
			return
22
		}
23
	}
24
25
	http.Redirect(w, r, "/"+a.Username, http.StatusSeeOther)
26
}

+ 1 - 1
html/article.html

@ -1,5 +1,5 @@
1 1
{{ define "title" }}{{ end }}
2
{{ define "style" }}{{ end }}
2
{{ define "styles" }}{{ end }}
3 3
{{ define "content" }}
4 4
    <article>
5 5
        <h3>

+ 6 - 13
html/blog.html

@ -3,27 +3,20 @@
3 3
<head>
4 4
    <meta charset="utf-8">
5 5
    <meta http-equiv="X-UC-Compatible" content="IE=edge">
6
    <meta name="viewport" content="width=device-width, initial-scale=1">
6
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no">
7 7
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
8 8
9 9
    <title>{{ template "title" . }}</title>
10 10
11
    <link rel="shortcut icon" type=image/png" href="">
12
    <link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
13
    <link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap-theme.min.css">
14
    <link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css">
15
    <link href="http://fonts.googleapis.com/css?family=Raleway:700,400" rel="stylesheet" type="text/css">
11
    <link rel="shortcut icon" type="image/png" href="">
12
    <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.95.3/css/materialize.min.css">
16 13
    {{ template "styles" . }}
17
18
    <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
19
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
20
    <!--[if lt IE 9]>
21
        <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
22
        <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
23
    <![endif]-->
24 14
</head>
25 15
<body>
26 16
    {{ template "content" . }}
17
18
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
19
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.95.3/js/materialize.min.js"></script>
27 20
    {{ template "scripts" . }}
28 21
</body>
29 22
</html>

+ 179 - 259
html/default.html

@ -1,302 +1,222 @@
1
{{ define "title" }}Loop{{ end }}
1
{{ define "title" }}Welcome to Loop!{{ end }}
2 2
{{ define "styles" }}
3 3
    <style type="text/css">
4
        /* Parallax base styles
5
        --------------------------------------------- */
6
7
        .parallax {
8
            height: 500px; /* fallback for older browsers */
9
            height: 100vh;
10
            overflow-x: hidden;
11
            overflow-y: auto;
12
            -webkit-perspective: 300px;
13
                    perspective: 300px;
14
            -webkit-perspective-origin-x: 100%;
15
                    perspective-origin-x: 100%;
16
        }
17
18
        .parallax-group {
19
            position: relative;
20
            height: 500px; /* fallback for older browsers */
21
            height: 100vh;
22
            -webkit-transform-style: preserve-3d;
23
                    transform-style: preserve-3d;
24
        }
25
26
        .parallax-layer {
27
            position: absolute;
28
            top: 0;
29
            left: 0;
30
            right: 0;
31
            bottom: 0;
32
            -webkit-transform-origin-x: 100%;
33
                    transform-origin-x: 100%;
34
        }
35
36
        .parallax-layer-fore {
37
            -webkit-transform: translateZ(90px) scale(.7);
38
                    transform: translateZ(90px) scale(.7);
39
            z-index: 1;
40
        }
41
42
        .parallax-layer-base {
43
            -webkit-transform: translateZ(0);
44
                    transform: translateZ(0);
45
            z-index: 4;
46
        }
47
48
        .parallax-layer-back {
49
            -webkit-transform: translateZ(-300px) scale(2);
50
                    transform: translateZ(-300px) scale(2);
51
            z-index: 3;
52
        }
53
54
        .parallax-layer-deep {
55
            -webkit-transform: translateZ(-600px) scale(3);
56
                    transform: translateZ(-600px) scale(3);
57
            z-index: 2;
58
        }
59
60
        /* Debugger styles - used to show the effect
61
        --------------------------------------------- */
62
63
        .debug {
64
            position: fixed;
65
            bottom: 0;
66
            right: 0;
67
            z-index: 999;
68
            background: rgba(0,0,0,.85);
69
            color: #fff;
70
            padding: .5em;
71
            /*border-radius: 0 0 5px 5px;*/
72
        }
73
        .debug-on .parallax-group {
74
            -webkit-transform: translate3d(800px, 0, -800px) rotateY(30deg);
75
                    transform: translate3d(700px, 0, -800px) rotateY(30deg);
76
        }
77
        .debug-on .parallax-layer {
78
            box-shadow: 0 0 0 2px #000;
79
            opacity: 0.9;
80
        }
81
        .parallax-group {
82
            -webkit-transition: -webkit-transform 0.5s;
83
                    transition: transform 0.5s;
84
        }
85
86
        /* demo styles
87
        --------------------------------------------- */
88
89
        body, html {
90
            overflow: hidden;
91
        }
92
93
        body {
94
            font: 100% / 1.5 Arial;
95
        }
96
97
        * {
98
            margin:0;
99
            padding:0;
100
        }
101
102
        .parallax {
103
            font-size: 200%;
104
            background: rgb(255, 249, 242);
105
        }
106
107
        /* centre the content in the parallax layers */
108
        .title {
109
            text-align: center;
110
            position: absolute;
111
            left: 50%;
112
            top: 50%;
113
            -webkit-transform: translate(-50%, -50%);
114
                    transform: translate(-50%, -50%);
4
        nav ul a,
5
        nav .brand-logo {
6
            color: #444;
115 7
        }
116 8
117
        /* style the groups
118
        --------------------------------------------- */
119
120
        #group1 {
121
            z-index: 5; /* slide over group 2 */
122
        }
123
        #group1 .parallax-layer-base {
124
            background: rgb(255, 249, 242);
9
        p {
10
            line-height: 2rem;
125 11
        }
126 12
127
        #group2 {
128
            z-index: 3; /* slide under groups 1 and 3 */
129
        }
130
        #group2 .parallax-layer-back {
131
            background: rgb(0, 0, 0);
132
            color: rgb(255, 249, 242);
13
        .button-collapse {
14
            color: #26a69a;
133 15
        }
134 16
135
        #group3 {
136
            z-index: 4; /* slide over group 2 and 4 */
137
        }
138
        #group3 .parallax-layer-base {
139
            background: rgb(255, 249, 242);
17
        .parallax-container {
18
            min-height: 380px;
19
            line-height: 0;
20
            height: auto;
21
            color: rgba(255, 255, 255, 0.9);
140 22
        }
141 23
142
        #group4 {
143
            z-index: 2; /* slide under group 3 and 5 */
144
        }
145
        #group4 .parallax-layer-deep {
146
            background: rgb(184, 223, 101);
24
        .parallax-container .section {
25
            width: 100%;
147 26
        }
148 27
149
        #group5 {
150
            z-index: 3; /* slide over group 4 and 6 */
151
        }
152
        #group5 .parallax-layer-base {
153
            background: rgb(214, 229, 100);
28
        @media only screen and (max-width: 992px) {
29
            .parallax-container .section {
30
                position: absolute;
31
                    top: 40%;
32
            }
33
            #index-banner .section {
34
                top: 10%;
35
            }
154 36
        }
155 37
156
        #group6 {
157
            z-index: 2; /* slide under group 5 and 7 */
158
        }
159
        #group6 .parallax-layer-back {
160
            background: rgb(245, 235, 100);
38
        @media only screen and (max-width: 600px) {
39
            #index-banner .section {
40
                top: 0;
41
            }
161 42
        }
162 43
163
        #group7 {
164
            z-index: 3; /* slide over group 7 */
44
        .icon-block {
45
            padding: 0 15px;
165 46
        }
166
        #group7 .parallax-layer-base {
167
            background: rgb(255, 241, 100);
168
        }
169
170 47
171
        /* misc
172
        --------------------------------------------- */
173
        .demo__info {
174
            position: absolute;
175
            z-index:100;
176
            bottom: 1vh;
177
            top: auto;
178
            font-size:80%;
179
            text-align:center;
180
            width: 100%;
181
        }
182
183
        .fa {
184
            max-width: 55px;
48
        footer.page-footer {
49
            margin: 0;
185 50
        }
186 51
    </style>
187
{{end}}
52
{{ end }}
188 53
{{ define "content" }}
189
    <div class="parallax">
190
        <div id="group1" class="parallax-group">
191
            <div class="parallax-layer parallax-layer-base">
192
                <div class="col-sm-6 text-center">
193
                    <img src="loop.png" alt="loop" class="img-responsive img-circle" style="display: inline;" />
54
    <nav class="white" role="navigation">
55
        <div class="nav-wrapper container">
56
            <a id="logo-container" href="#" class="brand-logo">Loop</a>
57
            <ul class="right">
58
                <li><a href="#logon">Log On</a></li>
59
            </ul>
60
            <ul id="nav-mobile" class="side-nav">
61
                <li><a href="#logon">Log On</a></li>
62
            </ul>
63
            <a href="#" data-activates="nav-mobile" class="button-collapse"><i class="mdi-navigation-menu"></i></a>
64
        </div>
65
    </nav>
66
67
    <div id="index-banner" class="parallax-container">
68
        <div class="section no-pad-bot">
69
            <div class="container">
70
                <br><br>
71
                <h1 class="header center teal-text text-lighten-2">Loop</h1>
72
                <div class="row center">
73
                    <h5 class="header col s12 black-text light">A modern platform aiming to tighten the feedback loop</h5>
74
                </div>
75
                <div class="row center">
76
                    <a href="#logon" id="download-button" class="btn-large waves-effect waves-light teal lighten-1">Get Started</a>
194 77
                </div>
195
                <div class="col-sm-5" style="padding-top: 5em;">
196
                    <h1>Loop</h1>
197
                    <p>Shortening the feedback loop in business and life.</p>
78
                <br><br>
79
            </div>
80
        </div>
81
        <div class="parallax">
82
            <img src="https://ununsplash.imgix.net/uploads/1413387158190559d80f7/6108b580" alt="Charles Forerunner">
83
        </div>
84
    </div>
198 85
199
                    <form action="" method="post" class="form form-horizontal">
200
                        <div class="form-group">
201
                            <div class="col-sm-6">
202
                                <input type="text" id="username" name="u" class="form-control" placeholder="Username" required autofocus />
86
    <div class="container">
87
        <div class="section">
88
            <div class="row">
89
                <div class="col s12 m4">
90
                    <div class="icon-block">
91
                        <h2 class="center brown-text"><i class="mdi-image-flash-on"></i></h2>
92
                        <h5 class="center">Speeds up development</h5>
93
                        <p class="light">
94
                            We did most of the heavy lifting for you to provide a default stylings that incorporate
95
                            our custom components. Additionally, we refined animations and transitions to provide a
96
                            smoother experience for developers.
97
                        </p>
98
                    </div>
99
                </div>
100
                <div class="col s12 m4">
101
                    <div class="icon-block">
102
                        <h2 class="center brown-text"><i class="mdi-social-group"></i></h2>
103
                        <h5 class="center">User Experience Focused</h5>
104
                        <p class="light">
105
                            By utilizing elements and principles of Material Design, we were able to create a
106
                            framework that incorporates components and animations that provide more feedback to
107
                            users. Additionally, a single underlying responsive system across all platforms allow
108
                            for a more unified user experience.
109
                        </p>
110
                    </div>
111
                </div>
112
                <div class="col s12 m4">
113
                    <div class="icon-block">
114
                        <h2 class="center brown-text"><i class="mdi-communication-forum"></i></h2>
115
                        <h5 class="center">Easy to collaborate</h5>
116
                        <p class="light">
117
                            We have provided detailed documentation as well as specific code examples to help new
118
                            users get started. We are also always open to feedback and can answer any questions a
119
                            user may have about Materialize.
120
                        </p>
121
                    </div>
122
                </div>
123
            </div>
124
        </div>
125
    </div>
126
127
    <div class="parallax-container valign-wrapper">
128
        <div class="section no-pad-bot">
129
            <div class="container">
130
                <div class="row center">
131
                    <h5 class="header col s12 light">A modern responsive front-end framework based on Material Design</h5>
132
                </div>
133
            </div>
134
        </div>
135
        <div class="parallax">
136
            <img src="https://unsplash.imgix.net/45/QDSMoAMTYaZoXpcwBjsL__DSC0104-1.jpg" alt="Aleksi Tappura">
137
        </div>
138
    </div>
139
140
    <div class="container">
141
        <div class="section">
142
            <div class="row">
143
                <div class="col l6 offset-l3 s12 center">
144
                    <a id="logon"></a>
145
                    <h3><i class="mdi-content-send brown-text"></i></h3>
146
                    <h4>Give it a try!</h4>
147
                    <p class="left-align light">
148
                        It is free to use
149
                    </p>
150
                    <form class="col s12" method="post" action="/logon">
151
                        <div class="row">
152
                            <div class="input-field col s12">
153
                                <input id="email" type="text" class="validate">
154
                                <label for="email">Email</label>
203 155
                            </div>
204
                            <div class="col-sm-6">
205
                                <input type="password" id="password" name="p" class="form-control" placeholder="Password" required />
156
                            <div class="input-field col s12">
157
                                <input id="password" type="password" class="validate">
158
                                <label for="password">Password</label>
206 159
                            </div>
207
                        </div>
208
                        <div class="form-group">
209
                            <div class="col-sm-offset-8 col-sm-4">
210
                                <button class="btn btn-lg btn-primary btn-block" type="submit" title="Sign in">Sign in</button>
160
                            <div class="input-field col s12">
161
                                <button class="btn waves-effect waves-light" type="submit" name="action">
162
                                    Submit
163
                                    <i class="mdi-content-send right"></i>
164
                                </button>
211 165
                            </div>
212 166
                        </div>
213 167
                    </form>
214 168
                </div>
215
                <div class="col-sm-1">&nbsp;</div>
216 169
            </div>
217 170
        </div>
218
        <div id="group2" class="parallax-group">
219
            <div class="parallax-layer parallax-layer-base">
220
            </div>
221
            <div class="parallax-layer parallax-layer-back">
222
                <div class="title">Features</div>
171
    </div>
172
173
    <div class="parallax-container valign-wrapper">
174
        <div class="section no-pad-bot">
175
            <div class="container">
176
                <div class="row center">
177
                    <h5 class="header col s12 light">A modern responsive front-end framework based on Material Design</h5>
178
                </div>
223 179
            </div>
224 180
        </div>
225
        <div id="group3" class="parallax-group">
226
            <div class="parallax-layer parallax-layer-base">
227
                <div class="container" style="padding-top: 5em;">
228
                    <div class="row">
229
                        <div class="col-sm-6">
230
                            <i class="pull-left fa fa-3x fa-cloud-download"></i>
231
                            <h3>Easy to install</h3>
232
                            <p>Compiled to a single binary deploying first-time installs and updates is incredibly simple.</p>
233
                        </div>
234
                        <div class="col-sm-6">
235
                            <i class="pull-left fa fa-3x fa-desktop"></i>
236
                            <h3>Cross-platform</h3>
237
                            <p>Loop runs everywhere! Just download the appropriate binary for one of the following platforms: Linux, Mac OS X, or Windows.</p>
238
                        </div>
239
                    </div>
240
                    <div class="row">
241
                        <div class="col-sm-6">
242
                            <i class="pull-left fa fa-3x fa-paper-plane"></i>
243
                            <h3>Lightweight</h3>
244
                            <p>No additional databases, dependencies on external resources, and on-demand processing keeps minimum requirements low.</p>
245
                        </div>
246
                        <div class="col-sm-6">
247
                            <i class="pull-left fa fa-3x fa-code"></i>
248
                            <h3>Open Source</h3>
249
                            <p>The project is licensed under the GPLv2 and can be tailored to suit your needs.</p>
250
                        </div>
251
                    </div>
252
                    <div class="row">
253
                        <div class="col-sm-6">
254
                            <i class="pull-left fa fa-3x fa-edit"></i>
255
                            <h3>Blogging</h3>
256
                            <p>Whether it is a simple note, todo list, or marketing for your business blogging is made simple by taking advantage of the simplicity of Markdown and ease of publishing.</p>
257
                        </div>
258
                        <div class="col-sm-6">
259
                            <i class="pull-left fa fa-3x fa-line-chart"></i>
260
                            <h3>Metrics</h3>
261
                            <p>Without understanding where you have started you cannot accurately gauge where you have gone. This is why metrics are stored with every action within the system.</p>
262
                        </div>
263
                    </div>
264
                    <div class="row">
265
                        <div class="col-sm-6">
266
                            <i class="pull-left fa fa-3x fa-credit-card"></i>
267
                            <h3>Payments</h3>
268
                            <p>Internal invoicing has never been so easy with built-in handling to Stripe.</p>
269
                        </div>
270
                        <div class="col-sm-6">
271
                            <i class="pull-left fa fa-3x fa-archive"></i>
272
                            <h3>Data storage</h3>
273
                            <p>Containers can store any file type making it simple to organize and store data privately in the cloud.</p>
274
                        </div>
275
                    </div>
181
        <div class="parallax">
182
            <img src="https://unsplash.imgix.net/uploads/1411724908903377d4696/2e9b0cb2" alt="Sergei Zolkin">
183
        </div>
184
    </div>
185
186
    <footer class="page-footer teal">
187
        <div class="container">
188
            <div class="row">
189
                <div class="col l9 s12">
190
                    <h5 class="white-text">Who are we?</h5>
191
                    <p class="grey-text text-lighten-4">
192
                        We are a team of developers constantly refining our internal processes to bring all parties
193
                        together during the project life cycle.
194
                    </p>
195
                </div>
196
                <div class="col l3 s12">
197
                    <h5 class="white-text">Connect</h5>
198
                    <ul>
199
                        <li><a class="white-text" href="https://revolvingcow.com">Company Site</a></li>
200
                        <li><a class="white-text" href="https://code.revolvingcow.com/revolvingcow/loop">Source Code</a></li>
201
                        <li><a class="white-text" href="mailto:info@revolvingcow.com">Email</a></li>
202
                    </ul>
276 203
                </div>
277 204
            </div>
278
            <div class="parallax-layer parallax-layer-back"></div>
279 205
        </div>
280
        <div id="group4" class="parallax-group">
281
            <div class="parallax-layer parallax-layer-base"></div>
282
            <div class="parallax-layer parallax-layer-deep">
206
        <div class="footer-copyright">
207
            <div class="container">
208
                Made by <a class="brown-text text-lighten-3" href="https://revolvingcow.com">Revolving Cow, LLC</a>
283 209
            </div>
284 210
        </div>
285
    </div>
286
287
    <div class="debug">
288
        <label>
289
            <input id="debugToggle" type="checkbox" />Debug
290
        </label>
291
    </div>
211
    </footer>
292 212
{{ end }}
293 213
{{ define "scripts" }}
294 214
    <script type="text/javascript">
295
        var debugInput = document.getElementById("debugToggle");
296
        function updateDebugState() {
297
            document.body.classList.toggle('debug-on', debugInput.checked);
298
        }
299
        debugInput.addEventListener("click", updateDebugState);
300
        updateDebugState();
215
        (function ($) {
216
            $(function () {
217
                $('.button-collapse').sideNav();
218
                $('.parallax').parallax();
219
            });
220
        })(jQuery);
301 221
    </script>
302 222
{{ end }}

+ 6 - 13
html/loop.html

@ -3,27 +3,20 @@
3 3
<head>
4 4
    <meta charset="utf-8">
5 5
    <meta http-equiv="X-UC-Compatible" content="IE=edge">
6
    <meta name="viewport" content="width=device-width, initial-scale=1">
6
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no">
7 7
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
8 8
9 9
    <title>{{ template "title" . }}</title>
10 10
11
    <link rel="shortcut icon" type=image/png" href="">
12
    <link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
13
    <link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap-theme.min.css">
14
    <link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css">
15
    <link href="http://fonts.googleapis.com/css?family=Raleway:700,400" rel="stylesheet" type="text/css">
11
    <link rel="shortcut icon" type="image/png" href="">
12
    <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.95.3/css/materialize.min.css">
16 13
    {{ template "styles" . }}
17
18
    <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
19
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
20
    <!--[if lt IE 9]>
21
        <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
22
        <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
23
    <![endif]-->
24 14
</head>
25 15
<body>
26 16
    {{ template "content" . }}
17
18
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
19
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.95.3/js/materialize.min.js"></script>
27 20
    {{ template "scripts" . }}
28 21
</body>
29 22
</html>

+ 2 - 2
html/workspace.html

@ -1,5 +1,5 @@
1
{{ define "title" }}Workspace{{ end }}
2
{{ define "style" }}{{ end }}
1
{{ define "title" }}Loop Workspace{{ end }}
2
{{ define "styles" }}{{ end }}
3 3
{{ define "content" }}
4 4
    <div class="row">
5 5
        <div class="col-sm-12">

二进制
loop


+ 8 - 8
main.go

@ -5,23 +5,23 @@ import (
5 5
	"net/http"
6 6
	"time"
7 7
8
	"code.revolvingcow.com/revolvingcow/loop/environment"
8 9
	"code.revolvingcow.com/revolvingcow/loop/handlers"
9 10
	"github.com/gorilla/mux"
10 11
)
11 12
12
const (
13
	UserFile = "loop_users"
14
)
15
16 13
func main() {
17 14
	log.Print("Configuring environment")
18 15
	time.Local = time.UTC
19
	ConfigureEnvironment()
16
	environment.ConfigureEnvironment()
20 17
21 18
	r := mux.NewRouter().StrictSlash(false)
22 19
	r.HandleFunc("/", handlers.DefaultHandler)
23 20
24
	content := r.PathPrefix("/{username}/content").Subrouter()
21
	auth := r.PathPrefix("/logon").Subrouter()
22
	auth.Methods("POST").HandlerFunc(handlers.LogonHandler)
23
24
	content := r.PathPrefix("/{username}").Subrouter()
25 25
	content.Methods("GET").HandlerFunc(handlers.ContentHandler)
26 26
27 27
	article := r.PathPrefix("/{username}/blog/{article}").Subrouter()
@ -30,6 +30,6 @@ func main() {
30 30
	blog := r.PathPrefix("/{username}/blog").Subrouter()
31 31
	blog.Methods("GET").HandlerFunc(handlers.BlogHandler)
32 32
33
	log.Print("Serving content on ", address())
34
	log.Fatal(http.ListenAndServe(address(), nil))
33
	log.Print("Serving content on ", environment.Address())
34
	log.Fatal(http.ListenAndServe(environment.Address(), r))
35 35
}

+ 1 - 1
markdown.go

@ -1,4 +1,4 @@
1
package main
1
package markdown
2 2
3 3
import (
4 4
	"github.com/microcosm-cc/bluemonday"

+ 1 - 1
markdown_test.go

@ -1,4 +1,4 @@
1
package main
1
package markdown
2 2
3 3
import "testing"
4 4

+ 6 - 4
security.go

@ -1,4 +1,4 @@
1
package main
1
package security
2 2
3 3
import (
4 4
	"crypto/aes"
@ -11,6 +11,8 @@ import (
11 11
	"fmt"
12 12
	"io"
13 13
	"strings"
14
15
	"code.revolvingcow.com/revolvingcow/loop/environment"
14 16
)
15 17
16 18
func encodeBase64(data []byte) string {
@ -76,7 +78,7 @@ func decrypt(text []byte, passphrase string) ([]byte, error) {
76 78
	return data, nil
77 79
}
78 80
79
func hash(clearText, salt string) []byte {
81
func Hash(clearText, salt string) []byte {
80 82
	h := md5.New()
81 83
	h.Write([]byte(clearText))
82 84
	return h.Sum(nil)
@ -94,6 +96,6 @@ func hashCredentials(username, passphrase, salt string) []byte {
94 96
	return sha.Sum(nil)
95 97
}
96 98
97
func generatePassphrase(username, passphrase string) string {
98
	return encodeBase64(hashCredentials(username, passphrase, salt()))
99
func GeneratePassphrase(username, passphrase string) string {
100
	return encodeBase64(hashCredentials(username, passphrase, environment.Salt()))
99 101
}

+ 4 - 2
security_test.go

@ -1,6 +1,8 @@
1
package main
1
package security
2 2
3
import "testing"
3
import (
4
	"testing"
5
)
4 6
5 7
func TestEncoding(t *testing.T) {
6 8
	clear := "encoding test"