Browse Source

Started to implement user auth

feature/frontv2
squeaky otter 4 years ago
parent
commit
0c0c135a77
Signed by: dashie GPG Key ID: C2D57B325840B755
11 changed files with 216 additions and 4 deletions
  1. +2
    -2
      bindata/bindata.go
  2. +11
    -0
      cmd/web.go
  3. +11
    -0
      conf/locale/locale_en-US.ini
  4. +26
    -0
      routers/user/auth.go
  5. +35
    -0
      static/css/custom.css
  6. +46
    -0
      stuff/markup/sanitizer.go
  7. +37
    -0
      stuff/markup/sanitizer_test.go
  8. +6
    -0
      stuff/template/template.go
  9. +20
    -0
      templates/base/alert.tmpl
  10. +2
    -2
      templates/base/head.tmpl
  11. +20
    -0
      templates/user/auth/login.tmpl

+ 2
- 2
bindata/bindata.go View File

@ -90,7 +90,7 @@ func confAppIni() (*asset, error) {
return a, nil
}
var _confLocaleLocale_enUsIni = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x01\x00\x00\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00")
var _confLocaleLocale_enUsIni = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x5c\x8e\x4d\xaa\x03\x21\x10\x84\xf7\x9e\x42\x3c\x80\x37\x78\xcb\xb7\xc8\x2e\x4c\x96\x43\x10\x13\x0b\xd3\xa0\xed\xd0\x2d\xe4\xfa\xc1\xc1\xfc\xee\xaa\xbe\xaa\x82\x5a\x4b\xcb\xc4\x67\xd3\xa9\x17\xd8\x3f\xeb\x4e\x94\xd9\x1e\xd8\x19\xa5\xcc\x81\xf8\x8b\xa1\x46\x2a\x83\xfc\x0f\x31\x7d\xd8\x4a\xbc\xe2\xd6\x4a\x82\xbc\x32\x1b\x53\x12\xa8\x7a\xef\x9d\xd9\xa2\xea\xbd\x49\x1a\xe9\x71\xea\x37\xfd\xdd\x3f\x1b\xfb\x54\x50\x51\x2f\x90\x50\xf7\x77\xcb\xb4\xb6\xc2\x19\xb3\x0a\x32\x69\x87\x7c\xfc\x5f\x26\x72\x8f\x00\x00\x00\xff\xff\x58\x0b\xf6\x39\xda\x00\x00\x00")
func confLocaleLocale_enUsIniBytes() ([]byte, error) {
return bindataRead(
@ -105,7 +105,7 @@ func confLocaleLocale_enUsIni() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "conf/locale/locale_en-US.ini", size: 0, mode: os.FileMode(420), modTime: time.Unix(1493941326, 0)}
info := bindataFileInfo{name: "conf/locale/locale_en-US.ini", size: 218, mode: os.FileMode(420), modTime: time.Unix(1494026007, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}


+ 11
- 0
cmd/web.go View File

@ -13,6 +13,7 @@ import (
"github.com/go-macaron/csrf"
"github.com/go-macaron/cache"
"github.com/go-macaron/i18n"
//"github.com/go-macaron/binding"
"strings"
"fmt"
log "gopkg.in/clog.v1"
@ -21,6 +22,7 @@ import (
"net/http/fcgi"
"os"
"dev.sigpipe.me/dashie/git.txt/models"
"dev.sigpipe.me/dashie/git.txt/routers/user"
)
var Web = cli.Command{
@ -118,8 +120,17 @@ func runWeb(ctx *cli.Context) error {
m := newMacaron()
//bindIgnErr := binding.BindIgnErr
m.Get("/", routers.Home)
m.Group("/user", func() {
m.Group("/login", func() {
m.Combo("").Get(user.Login)
})
})
m.Get("/register", user.Register)
// robots.txt
m.Get("/robots.txt", func(ctx *context.Context) {
if setting.HasRobotsTxt {


+ 11
- 0
conf/locale/locale_en-US.ini View File

@ -0,0 +1,11 @@
[login]
title = "Sign In"
sign_in = "Sign In"
email = "Email"
email_placeholder = "Email address..."
password = "Password"
password_placeholder = "Password..."
remember_me = "Remember me"
[register]
title = "Register"

+ 26
- 0
routers/user/auth.go View File

@ -0,0 +1,26 @@
package user
import (
"dev.sigpipe.me/dashie/git.txt/context"
)
const (
LOGIN = "user/auth/login"
REGISTER = "user/auth/register"
ACTIVATE = "user/auth/activate"
FORGOT_PASSWORD = "user/auth/forgot_password"
RESET_PASSWORD = "user/auth/reset_password"
)
func Login(ctx *context.Context) {
ctx.Title("login.title")
// TODO: auto login remember_me
ctx.HTML(200, LOGIN)
}
func Register(ctx *context.Context) {
ctx.Title("register.title")
ctx.HTML(200, REGISTER)
}

+ 35
- 0
static/css/custom.css View File

@ -19,4 +19,39 @@ footer .left {
footer .right {
float: right;
}
.form-signin {
max-width: 330px;
padding: 15px;
margin: 0 auto;
}
.form-signin .form-signin-heading,
.form-signin .checkbox {
margin-bottom: 10px;
}
.form-signin .checkbox {
font-weight: normal;
}
.form-signin .form-control {
position: relative;
height: auto;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
padding: 10px;
font-size: 16px;
}
.form-signin .form-control:focus {
z-index: 2;
}
.form-signin input[type="email"] {
margin-bottom: -1px;
border-bottom-right-radius: 0;
border-bottom-left-radius: 0;
}
.form-signin input[type="password"] {
margin-bottom: 10px;
border-top-left-radius: 0;
border-top-right-radius: 0;
}

+ 46
- 0
stuff/markup/sanitizer.go View File

@ -0,0 +1,46 @@
// Copyright 2017 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style license
package markup
import (
"regexp"
"sync"
"github.com/microcosm-cc/bluemonday"
)
// Sanitizer is a protection wrapper of *bluemonday.Policy which does not allow
// any modification to the underlying policies once it's been created.
type Sanitizer struct {
policy *bluemonday.Policy
init sync.Once
}
var sanitizer = &Sanitizer{
policy: bluemonday.UGCPolicy(),
}
// NewSanitizer initializes sanitizer with allowed attributes based on settings.
// Multiple calls to this function will only create one instance of Sanitizer during
// entire application lifecycle.
func NewSanitizer() {
sanitizer.init.Do(func() {
// We only want to allow HighlightJS specific classes for code blocks
sanitizer.policy.AllowAttrs("class").Matching(regexp.MustCompile(`^language-\w+$`)).OnElements("code")
// Checkboxes
sanitizer.policy.AllowAttrs("type").Matching(regexp.MustCompile(`^checkbox$`)).OnElements("input")
sanitizer.policy.AllowAttrs("checked", "disabled").OnElements("input")
})
}
// Sanitize takes a string that contains a HTML fragment or document and applies policy whitelist.
func Sanitize(s string) string {
return sanitizer.policy.Sanitize(s)
}
// SanitizeBytes takes a []byte slice that contains a HTML fragment or document and applies policy whitelist.
func SanitizeBytes(b []byte) []byte {
return sanitizer.policy.SanitizeBytes(b)
}

+ 37
- 0
stuff/markup/sanitizer_test.go View File

@ -0,0 +1,37 @@
// Copyright 2017 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style license
package markup_test
import (
"testing"
. "github.com/smartystreets/goconvey/convey"
. "dev.sigpipe.me/dashie/git.txt/stuff/markup"
)
func Test_Sanitizer(t *testing.T) {
NewSanitizer()
Convey("Sanitize HTML string and bytes", t, func() {
testCases := []string{
// Regular
`<a onblur="alert(secret)" href="http://www.google.com">Google</a>`, `<a href="http://www.google.com" rel="nofollow">Google</a>`,
// Code highlighting class
`<code class="random string"></code>`, `<code></code>`,
`<code class="language-random ui tab active menu attached animating sidebar following bar center"></code>`, `<code></code>`,
`<code class="language-go"></code>`, `<code class="language-go"></code>`,
// Input checkbox
`<input type="hidden">`, ``,
`<input type="checkbox">`, `<input type="checkbox">`,
`<input checked disabled autofocus>`, `<input checked="" disabled="">`,
}
for i := 0; i < len(testCases); i += 2 {
So(Sanitize(testCases[i]), ShouldEqual, testCases[i+1])
So(string(SanitizeBytes([]byte(testCases[i]))), ShouldEqual, testCases[i+1])
}
})
}

+ 6
- 0
stuff/template/template.go View File

@ -12,6 +12,7 @@ import (
"dev.sigpipe.me/dashie/git.txt/stuff/tool"
"github.com/microcosm-cc/bluemonday"
"container/list"
"dev.sigpipe.me/dashie/git.txt/stuff/markup"
)
func NewFuncMap() []template.FuncMap {
@ -45,6 +46,7 @@ func NewFuncMap() []template.FuncMap {
},
"Safe": Safe,
"Sanitize": bluemonday.UGCPolicy().Sanitize,
"Str2html": Str2html,
"Add": func(a, b int) int {
return a + b
},
@ -104,3 +106,7 @@ func Sha1(str string) string {
func EscapePound(str string) string {
return strings.NewReplacer("%", "%25", "#", "%23", " ", "%20", "?", "%3F").Replace(str)
}
func Str2html(raw string) template.HTML {
return template.HTML(markup.Sanitize(raw))
}

+ 20
- 0
templates/base/alert.tmpl View File

@ -0,0 +1,20 @@
{{if .Flash.ErrorMsg}}
<div class="ui negative message">
<p>{{.Flash.ErrorMsg | Str2html}}</p>
</div>
{{end}}
{{if .Flash.WarningMsg}}
<div class="ui warning message">
<p>{{.Flash.WarningMsg | Str2html}}</p>
</div>
{{end}}
{{if .Flash.SuccessMsg}}
<div class="ui positive message">
<p>{{.Flash.SuccessMsg | Str2html}}</p>
</div>
{{end}}
{{if .Flash.InfoMsg}}
<div class="ui info message">
<p>{{.Flash.InfoMsg | Str2html}}</p>
</div>
{{end}}

+ 2
- 2
templates/base/head.tmpl View File

@ -35,7 +35,7 @@
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">{{AppName}}</a>
<a class="navbar-brand" href="{{AppSubURL}}/">{{AppName}}</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
@ -50,7 +50,7 @@
{{if CanRegister}}
<li><a href="{{AppSubURL}}/register">Register</a></li>
{{end}}
<li><a href="{{AppSubURL}}/login">Login</a></li>
<li><a href="{{AppSubURL}}/user/login">Login</a></li>
{{end}}
</ul>
</div><!--/.nav-collapse -->


+ 20
- 0
templates/user/auth/login.tmpl View File

@ -0,0 +1,20 @@
{{template "base/head" .}}
<form class="form-signin" action="{{.Link}}" method="post">
{{.CSRFTokenHTML}}
<h2 class="form-signin-heading">{{.i18n.Tr "login.sign_in"}}</h2>
{{template "base/alert" .}}
<label for="inputEmail" class="sr-only">{{.i18n.Tr "login.email"}}</label>
<input type="email" id="inputEmail" class="form-control {{if .Err_UserName}}error{{end}}" placeholder='{{.i18n.Tr "login.email_placeholder"}}' required autofocus>
<label for="inputPassword" class="sr-only">{{.i18n.Tr "login.password"}}</label>
<input type="password" id="inputPassword" class="form-control {{if .Err_UserName}}error{{end}}" placeholder='{{.i18n.Tr "login.password_placeholder"}}' required>
<div class="checkbox">
<label>
<input type="checkbox" value="remember-me"> {{.i18n.Tr "login.remember_me"}}
</label>
</div>
<button class="btn btn-lg btn-primary btn-block" type="submit">{{.i18n.Tr "login.sign_in"}}</button>
</form>
{{template "base/footer" .}}