Browse Source

use tango instead of xweb for web interface

pull/3/head
Lunny Xiao 4 years ago
parent
commit
316b1a3554
58 changed files with 524 additions and 358 deletions
  1. +1
    -1
      config.ini
  2. +4
    -2
      main.go
  3. +0
    -0
      public/css/bootstrap-theme.css
  4. +0
    -0
      public/css/bootstrap-theme.css.map
  5. +0
    -0
      public/css/bootstrap-theme.min.css
  6. +0
    -0
      public/css/bootstrap.css
  7. +0
    -0
      public/css/bootstrap.css.map
  8. +0
    -0
      public/css/bootstrap.min.css
  9. +0
    -0
      public/font/FontAwesome.otf
  10. +0
    -0
      public/font/fontawesome-webfont.eot
  11. +0
    -0
      public/font/fontawesome-webfont.svg
  12. +0
    -0
      public/font/fontawesome-webfont.ttf
  13. +0
    -0
      public/font/fontawesome-webfont.woff
  14. +0
    -0
      public/fonts/glyphicons-halflings-regular.eot
  15. +0
    -0
      public/fonts/glyphicons-halflings-regular.svg
  16. +0
    -0
      public/fonts/glyphicons-halflings-regular.ttf
  17. +0
    -0
      public/fonts/glyphicons-halflings-regular.woff
  18. +0
    -0
      public/img/alipay.png
  19. +0
    -0
      public/img/arrow left.svg
  20. +0
    -0
      public/img/arrow right.svg
  21. +0
    -0
      public/img/bg.jpg
  22. +0
    -0
      public/img/brands/gocms.png
  23. +0
    -0
      public/img/brands/gogs.png
  24. +0
    -0
      public/img/brands/revelhat.png
  25. +0
    -0
      public/img/brands/sudochina.jpg
  26. +0
    -0
      public/img/community/IRC.png
  27. +0
    -0
      public/img/community/github.png
  28. +0
    -0
      public/img/community/google-groups.png
  29. +0
    -0
      public/img/community/stackoverflow.png
  30. +0
    -0
      public/img/community/twitter.png
  31. +0
    -0
      public/img/favicon.png
  32. +0
    -0
      public/img/footer-links.png
  33. +0
    -0
      public/img/fork-us-on-github.png
  34. +0
    -0
      public/img/website-footer.svg
  35. +0
    -0
      public/js/bootstrap.js
  36. +0
    -0
      public/js/bootstrap.min.js
  37. +0
    -0
      public/js/jquery.min.js
  38. +13
    -0
      templates/base/base.html
  39. +11
    -0
      templates/base/common.html
  40. +7
    -0
      templates/base/common_nohead.html
  41. +0
    -0
      templates/base/foot.html
  42. +8
    -0
      templates/base/head.html
  43. +5
    -5
      templates/base/nav.html
  44. +7
    -14
      templates/group/add.html
  45. +5
    -12
      templates/group/edit.html
  46. +5
    -12
      templates/group/list.html
  47. +0
    -9
      templates/head.html
  48. +3
    -3
      templates/login.html
  49. +22
    -25
      templates/perm/list.html
  50. +7
    -14
      templates/user/add.html
  51. +8
    -15
      templates/user/chgpass.html
  52. +10
    -17
      templates/user/edit.html
  53. +7
    -14
      templates/user/list.html
  54. +108
    -50
      web/actions.go
  55. +46
    -31
      web/group.go
  56. +58
    -30
      web/perm.go
  57. +113
    -91
      web/user.go
  58. +76
    -13
      web/web.go

+ 1
- 1
config.ini View File

@@ -6,7 +6,7 @@ port=2121
[web]
enable=true
listen=:8181
ssl=true
tls=false

[admin]
user=admin


+ 4
- 2
main.go View File

@@ -83,9 +83,11 @@ func main() {
weblisten, _ := cfg.GetValue("web", "listen")
admin, _ := cfg.GetValue("admin", "user")
pass, _ := cfg.GetValue("admin", "pass")
ssl, _ := cfg.Bool("web", "ssl")
tls, _ := cfg.Bool("web", "tls")
certFile, _ := cfg.GetValue("web", "certFile")
keyFile, _ := cfg.GetValue("web", "keyFile")

go web.Web(weblisten, "static", "templates", admin, pass, ssl)
go web.Web(weblisten, "static", "templates", admin, pass, tls, certFile, keyFile)
}

ftpName, _ := cfg.GetValue("server", "name")


static/css/bootstrap-theme.css → public/css/bootstrap-theme.css View File


static/css/bootstrap-theme.css.map → public/css/bootstrap-theme.css.map View File


static/css/bootstrap-theme.min.css → public/css/bootstrap-theme.min.css View File


static/css/bootstrap.css → public/css/bootstrap.css View File


static/css/bootstrap.css.map → public/css/bootstrap.css.map View File


static/css/bootstrap.min.css → public/css/bootstrap.min.css View File


static/font/FontAwesome.otf → public/font/FontAwesome.otf View File


static/font/fontawesome-webfont.eot → public/font/fontawesome-webfont.eot View File


static/font/fontawesome-webfont.svg → public/font/fontawesome-webfont.svg View File


static/font/fontawesome-webfont.ttf → public/font/fontawesome-webfont.ttf View File


static/font/fontawesome-webfont.woff → public/font/fontawesome-webfont.woff View File


static/fonts/glyphicons-halflings-regular.eot → public/fonts/glyphicons-halflings-regular.eot View File


static/fonts/glyphicons-halflings-regular.svg → public/fonts/glyphicons-halflings-regular.svg View File


static/fonts/glyphicons-halflings-regular.ttf → public/fonts/glyphicons-halflings-regular.ttf View File


static/fonts/glyphicons-halflings-regular.woff → public/fonts/glyphicons-halflings-regular.woff View File


static/img/alipay.png → public/img/alipay.png View File


static/img/arrow left.svg → public/img/arrow left.svg View File


static/img/arrow right.svg → public/img/arrow right.svg View File


static/img/bg.jpg → public/img/bg.jpg View File


static/img/brands/gocms.png → public/img/brands/gocms.png View File


static/img/brands/gogs.png → public/img/brands/gogs.png View File


static/img/brands/revelhat.png → public/img/brands/revelhat.png View File


static/img/brands/sudochina.jpg → public/img/brands/sudochina.jpg View File


static/img/community/IRC.png → public/img/community/IRC.png View File


static/img/community/github.png → public/img/community/github.png View File


static/img/community/google-groups.png → public/img/community/google-groups.png View File


static/img/community/stackoverflow.png → public/img/community/stackoverflow.png View File


static/img/community/twitter.png → public/img/community/twitter.png View File


static/img/favicon.png → public/img/favicon.png View File


static/img/footer-links.png → public/img/footer-links.png View File


static/img/fork-us-on-github.png → public/img/fork-us-on-github.png View File


static/img/website-footer.svg → public/img/website-footer.svg View File


static/js/bootstrap.js → public/js/bootstrap.js View File


static/js/bootstrap.min.js → public/js/bootstrap.min.js View File


static/js/jquery.min.js → public/js/jquery.min.js View File


+ 13
- 0
templates/base/base.html View File

@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="zh-cn">
<head>
{{template "head" .}}
</head>
<body>
<div class="container">
{{template "nav" .}}
{{template "body" .}}
</div>
{{template "footer" .}}
</body>
</html>

+ 11
- 0
templates/base/common.html View File

@@ -0,0 +1,11 @@
{{define "head"}}
{{template "base/head.html" .}}
{{end}}

{{define "nav"}}
{{template "base/nav.html" .}}
{{end}}

{{define "footer"}}
{{template "base/foot.html" .}}
{{end}}

+ 7
- 0
templates/base/common_nohead.html View File

@@ -0,0 +1,7 @@
{{define "nav"}}
{{template "base/nav.html" .}}
{{end}}

{{define "footer"}}
{{template "base/foot.html" .}}
{{end}}

templates/foot.html → templates/base/foot.html View File


+ 8
- 0
templates/base/head.html View File

@@ -0,0 +1,8 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/public/css/bootstrap-theme.css"/>
<link href="/public/css/bootstrap.css" rel="stylesheet">
<script src="/public/js/jquery.min.js"></script>
<script src="/public/js/bootstrap.js"></script>
<link rel="stylesheet" href="/public/css/bootstrap-theme.css" />

templates/nav.html → templates/base/nav.html View File

@@ -17,14 +17,14 @@
</div>
<div class="collapse navbar-collapse" role="navigation" id="navbar-collapse">
<ul class="nav navbar-nav">
{{if IsAdmin}}
<li{{if isCurModule 1}} class="active"{{end}}><a href="/user">用户管理</a></li>
<li{{if isCurModule 2}} class="active"{{end}}><a href="/group">组管理</a></li>
<li{{if isCurModule 3}} class="active"{{end}}><a href="/perm">权限管理</a></li>
{{if .IsAdmin}}
<li{{if call .isCurModule 1}} class="active"{{end}}><a href="/user">用户管理</a></li>
<li{{if call .isCurModule 2}} class="active"{{end}}><a href="/group">组管理</a></li>
<li{{if call .isCurModule 3}} class="active"{{end}}><a href="/perm">权限管理</a></li>
{{end}}
</ul>
<ul class="nav navbar-nav navbar-right">
<li{{if isCurModule 4}} class="active"{{end}}><a href="/user/chgpass">修改密码</a></li>
<li{{if call .isCurModule 4}} class="active"{{end}}><a href="/user/chgpass">修改密码</a></li>
<li><a href="/logout">退出 </a></li>
</ul>
</div>

+ 7
- 14
templates/group/add.html View File

@@ -1,14 +1,10 @@
<!DOCTYPE html>
<html lang="zh-cn">
<head>
{{include "head.html"}}
</head>
<body>
<div class="container">
{{include "nav.html"}}
<div style="padding:10px;padding-top:60px">
{{template "base/base.html" .}}
{{template "base/common.html" .}}

{{define "body"}}
<div style="padding:10px;padding-top:60px">
<form class="form-horizontal" method="post">
{{XsrfFormHtml}}
{{.XsrfFormHtml}}
<legend>添加组</legend>
<div class="control-group">
<label class="control-label" for="inputEmail">组名称:</label>
@@ -22,7 +18,4 @@
</div>
</form>
</div>
</div>
{{include "foot.html"}}
</body>
</html>
{{end}}

+ 5
- 12
templates/group/edit.html View File

@@ -1,11 +1,7 @@
<!DOCTYPE html>
<html lang="zh-cn">
<head>
{{include "head.html"}}
</head>
<body>
<div class="container">
{{include "nav.html"}}
{{template "base/base.html" .}}
{{template "base/common.html" .}}

{{define "body"}}
<div style="padding:10px;padding-top:60px">
<div class="row"><legend>修改组:{{.T.user.Name}}</legend></div>
<div class="row">
@@ -40,7 +36,4 @@
</div>
</div>
</div>
</div>
{{include "foot.html"}}
</body>
</html>
{{end}}

+ 5
- 12
templates/group/list.html View File

@@ -1,11 +1,7 @@
<!DOCTYPE html>
<html lang="zh-cn">
<head>
{{include "head.html"}}
</head>
<body>
<div class="container">
{{include "nav.html"}}
{{template "base/base.html" .}}
{{template "base/common.html" .}}

{{define "body"}}
<div class="text-right" style="padding:10px;padding-top:60px"><a href="/group/add" class="btn btn-large btn-primary">添加</a>
</div>
<table class="table table-bordered table-hover">
@@ -24,7 +20,4 @@
{{end}}
</tbody>
</table>
</div>
{{include "foot.html"}}
</body>
</html>
{{end}}

+ 0
- 9
templates/head.html View File

@@ -1,9 +0,0 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="{{StaticUrl "css/bootstrap-theme.css"}}"/>
<link href="{{StaticUrl "css/bootstrap.css"}}" rel="stylesheet">
<script src="{{StaticUrl "js/jquery.min.js"}}"></script>
<script src="{{StaticUrl "js/bootstrap.js"}}"></script>
<link rel="stylesheet" href="{{StaticUrl "css/bootstrap-theme.css"}}" />
<!--<link rel="stylesheet" href="{{StaticUrl "css/font-awesome.min.css"}}" />-->

+ 3
- 3
templates/login.html View File

@@ -1,7 +1,7 @@
<!DOCTYPE html>
<html lang="zh-cn">
<head>
{{include "head.html"}}
{{template "base/head.html" .}}
<style type="text/css">
body {
padding-top: 40px;
@@ -39,11 +39,11 @@
<body>
<div class="container">
<form class="form-signin" method="post">
{{XsrfFormHtml}}
{{.XsrfFormHtml}}
<h2 class="form-signin-heading">GoFtp管理系统</h2>
<input name="name" type="text" class="input-block-level" placeholder="账号">
<input name="pass" type="password" class="input-block-level" placeholder="密码">
<input type="submit" value="登录" class="btn btn-large btn-primary">&nbsp; <font color=red>{{.T.msg}}</font>
<input type="submit" value="登录" class="btn btn-large btn-primary">&nbsp; <font color=red>{{.msg}}</font>
</form>
</div>
</body>

+ 22
- 25
templates/perm/list.html View File

@@ -1,7 +1,8 @@
<!DOCTYPE html>
<html lang="zh-cn">
<head>
{{include "head.html"}}
{{template "base/base.html" .}}
{{template "base/common_nohead.html" .}}

{{define "head"}}
{{template "base/head.html"}}
<script>
function updateGroup(name, newgroup) {
$.ajax({
@@ -56,13 +57,12 @@ $(function() {
})
})
</script>
</head>
<body>
<div class="container">
{{include "nav.html"}}
<div class="row" style="padding:10px;padding-top:60px">
{{end}}

{{define "body"}}
<div class="row" style="padding:10px;padding-top:60px">
<div class="col-md-10">
当前目录:{{.T.path}}
当前目录:{{.path}}
</div>
<div class="col-md-2 text-right">
</div>
@@ -74,14 +74,14 @@ $(function() {
<th>权限(Others)</th><th>操作</th>
</thead>
<tbody>
{{$parent := .T.parent}}
{{if ne .T.path "/"}}
{{$parent := .parent}}
{{if ne .path "/"}}
<tr><td colspan="8"><a href="/perm/?path={{$parent}}">..</a></td>
</tr>
{{end}}
{{$users := .T.users}}
{{$groups := .T.groups}}
{{range .T.infos}}
{{$users := .users}}
{{$groups := .groups}}
{{range .infos}}
<tr><td>
{{$name := .Name}}
{{$owner := .Owner}}
@@ -102,17 +102,14 @@ $(function() {
<option{{if eq $group .}} selected{{end}}>{{.}}</option>
{{end}}
</select></td>
<td><input id="owner_r_{{$name}}" class="check" type="checkbox"{{if hasPerm .Mode 1 "r"}} checked{{end}}> r
<input id="owner_w_{{$name}}" class="check" type="checkbox"{{if hasPerm .Mode 2 "w"}} checked{{end}}> w</td>
<td><input id="group_r_{{$name}}" class="check" type="checkbox"{{if hasPerm .Mode 4 "r"}} checked{{end}}> r
<input id="group_w_{{$name}}" class="check" type="checkbox"{{if hasPerm .Mode 5 "w"}} checked{{end}}> w</td>
<td><input id="other_r_{{$name}}" class="check" type="checkbox"{{if hasPerm .Mode 7 "r"}} checked{{end}}> r
<input id="other_w_{{$name}}" class="check" type="checkbox"{{if hasPerm .Mode 8 "w"}} checked{{end}}> w</td>
<td><input id="owner_r_{{$name}}" class="check" type="checkbox"{{if call $.hasPerm .Mode 1 "r"}} checked{{end}}> r
<input id="owner_w_{{$name}}" class="check" type="checkbox"{{if call $.hasPerm .Mode 2 "w"}} checked{{end}}> w</td>
<td><input id="group_r_{{$name}}" class="check" type="checkbox"{{if call $.hasPerm .Mode 4 "r"}} checked{{end}}> r
<input id="group_w_{{$name}}" class="check" type="checkbox"{{if call $.hasPerm .Mode 5 "w"}} checked{{end}}> w</td>
<td><input id="other_r_{{$name}}" class="check" type="checkbox"{{if call $.hasPerm .Mode 7 "r"}} checked{{end}}> r
<input id="other_w_{{$name}}" class="check" type="checkbox"{{if call $.hasPerm .Mode 8 "w"}} checked{{end}}> w</td>
<td> </td></tr>
{{end}}
</tbody>
</table>
</div>
{{include "foot.html"}}
</body>
</html>
{{end}}

+ 7
- 14
templates/user/add.html View File

@@ -1,14 +1,10 @@
<!DOCTYPE html>
<html lang="zh-cn">
<head>
{{include "head.html"}}
</head>
<body>
<div class="container">
{{include "nav.html"}}
<div style="padding:10px;padding-top:60px">
{{template "base/base.html" .}}
{{template "base/common.html" .}}

{{define "body"}}
<div style="padding:10px;padding-top:60px">
<form class="form-horizontal" method="post">
{{XsrfFormHtml}}
{{.XsrfFormHtml}}
<legend>添加账号</legend>
<div class="control-group">
<label class="control-label" for="inputEmail">账号名称:</label>
@@ -28,7 +24,4 @@
</div>
</form>
</div>
</div>
{{include "foot.html"}}
</body>
</html>
{{end}}

+ 8
- 15
templates/user/chgpass.html View File

@@ -1,18 +1,14 @@
<!DOCTYPE html>
<html lang="zh-cn">
<head>
{{include "head.html"}}
</head>
<body>
<div class="container">
{{include "nav.html"}}
<div style="padding:10px;padding-top:60px">
{{template "base/base.html" .}}
{{template "base/common.html" .}}

{{define "body"}}
<div style="padding:10px;padding-top:60px">
<form class="form-horizontal" method="post">
{{XsrfFormHtml}}
{{.XsrfFormHtml}}
<legend>修改密码</legend>
<div class="control-group">
<label class="control-label" for="inputEmail">账号名称:</label>
<div class="controls"><input type="text" name="name" readonly value="{{session "userId"}}" />
<div class="controls"><input type="text" name="name" readonly value="{{.userId}}" />
</div>
</div>
<div class="control-group">
@@ -28,7 +24,4 @@
</div>
</form>
</div>
</div>
{{include "foot.html"}}
</body>
</html>
{{end}}

+ 10
- 17
templates/user/edit.html View File

@@ -1,25 +1,21 @@
<!DOCTYPE html>
<html lang="zh-cn">
<head>
{{include "head.html"}}
</head>
<body>
<div class="container">
{{include "nav.html"}}
<div style="padding:10px;padding-top:60px">
{{template "base/base.html" .}}
{{template "base/common.html" .}}

{{define "body"}}
<div style="padding:10px;padding-top:60px">
<form class="form-horizontal" method="post">
{{XsrfFormHtml}}
<legend>修改账号:{{.T.user.Name}}</legend>
{{.XsrfFormHtml}}
<legend>修改账号:{{.user.Name}}</legend>
<div class="control-group">
<label class="control-label" for="inputEmail">账号名称:</label>
<div class="controls">
<input type="text" name="name" value="{{.T.user.Name}}"/>
<input type="text" name="name" value="{{.user.Name}}"/>
</div>
</div>
<div class="control-group">
<label class="control-label" for="inputEmail">
账号密码:</label>
<div class="controls"><input type="password" name="pass" value="{{.T.user.Pass}}"/>
<div class="controls"><input type="password" name="pass" value="{{.user.Pass}}"/>
</div>
</div>
<div class="control-group">
@@ -29,7 +25,4 @@
</div>
</form>
</div>
</div>
{{include "foot.html"}}
</body>
</html>
{{end}}

+ 7
- 14
templates/user/list.html View File

@@ -1,11 +1,7 @@
<!DOCTYPE html>
<html lang="zh-cn">
<head>
{{include "head.html"}}
</head>
<body>
<div class="container">
{{include "nav.html"}}
{{template "base/base.html" .}}
{{template "base/common.html" .}}

{{define "body"}}
<div class="text-right" style="padding:10px;padding-top:60px"><a href="/user/add" class="btn btn-large btn-primary">添加</a>
</div>
<table class="table table-bordered table-hover">
@@ -13,8 +9,8 @@
<th>用户名</th><th>创建时间</th><th>操作</th>
</thead>
<tbody>
{{$admin := .T.admin}}
{{range .T.users}}
{{$admin := .admin}}
{{range .users}}
<tr><td>{{.Name}}</td><td></td>
<td>
{{if ne .Name $admin}}
@@ -24,7 +20,4 @@
{{end}}
</tbody>
</table>
</div>
{{include "foot.html"}}
</body>
</html>
{{end}}

+ 108
- 50
web/actions.go View File

@@ -1,76 +1,134 @@
package web

import "github.com/go-xweb/xweb"
import (
"fmt"

"github.com/lunny/tango"
"github.com/tango-contrib/binding"
"github.com/tango-contrib/renders"
"github.com/tango-contrib/session"
"github.com/tango-contrib/xsrf"
)

var _ auther = new(BaseAction)

type BaseAction struct {
*xweb.Action
renders.Renderer
session.Session
tango.Ctx
binding.Binder
curModule int
}

func (a *BaseAction) AskLogin() bool {
return false
}

type BaseAuthAction struct {
BaseAction
}

func (a *BaseAuthAction) AskLogin() bool {
return true
}

func (a *BaseAction) IsLogin() bool {
s := a.GetSession("userId")
return s != nil
id := a.Session.Get("userId")
fmt.Println(id)
return id != nil
}

func (a *BaseAction) SetLogin(user string) {
a.Session.Set("userId", user)
}

func (a *BaseAction) LoginUserId() string {
userId := a.Session.Get("userId")
if userId == nil {
return ""
}
return userId.(string)
}

func (a *BaseAction) Logout() {
a.Session.Del("userId")
}

func (a *BaseAction) IsAdmin() bool {
s := a.GetSession("userId")
s := a.Session.Get("userId")
return s != nil && s.(string) == adminUser
}

func (a *BaseAction) Init() {
a.AddTmplVars(&xweb.T{
"IsLogin": a.IsLogin,
"IsAdmin": a.IsAdmin,
})
func (a *BaseAction) Render(tmpl string, vars ...renders.T) error {
var t = renders.T{
"IsLogin": a.IsLogin(),
"IsAdmin": a.IsAdmin(),
"isCurModule": func(module int) bool {
return module == a.curModule
},
}
if len(vars) > 0 {
t.Merge(vars[0])
}
return a.Renderer.Render(tmpl, t)
}

type MainAction struct {
BaseAction
}

get xweb.Mapper `xweb:"/"`
login xweb.Mapper
logout xweb.Mapper
func (a *MainAction) Get() {
a.Redirect("/user")
}

func (a *MainAction) Get() error {
return a.Go("get", &UserAction{})
type LoginAction struct {
BaseAction
xsrf.Checker
}

func (a *MainAction) Logout() {
a.DelSession("userId")
a.Redirect("/")
func (a *LoginAction) Get() error {
return a.Render("login.html", renders.T{
"XsrfFormHtml": a.Checker.XsrfFormHtml(),
})
}

func (a *MainAction) Login() error {
if a.Method() == "GET" {
return a.Render("login.html")
} else if a.Method() == "POST" {
user := new(User)
err := a.MapForm(user, "")
if err != nil {
return err
}

if user.Name == "" || user.Pass == "" {
return a.Render("login.html", &xweb.T{
"msg": "用户名或者密码错误",
})
}

p, err := DB.GetUser(user.Name)
if err != nil {
return err
}
if p != user.Pass {
return a.Render("login.html", &xweb.T{
"msg": "用户名或者密码错误",
})
}

a.SetSession("userId", user.Name)
if a.IsAdmin() {
return a.Go("get", &UserAction{})
}
return a.Go("chgpass", &UserAction{})
func (a *LoginAction) Post() error {
var user User
errs := a.Bind(&user)
if errs.Len() > 0 {
return errs[0]
}

if user.Name == "" || user.Pass == "" {
return a.Render("login.html", renders.T{
"msg": "用户名或者密码错误",
})
}

p, err := DB.GetUser(user.Name)
if err != nil {
return err
}
return xweb.NotSupported()
if p != user.Pass {
return a.Render("login.html", renders.T{
"msg": "用户名或者密码错误",
})
}

a.SetLogin(user.Name)
if a.IsAdmin() {
a.Redirect("/user")
return nil
}
a.Redirect("/user/chgpass")
return nil
}

type LogoutAction struct {
BaseAuthAction
}

func (a *LogoutAction) Get() {
a.Logout()
a.Redirect("/")
}

+ 46
- 31
web/group.go View File

@@ -1,22 +1,20 @@
package web

import "github.com/go-xweb/xweb"
import (
"github.com/tango-contrib/renders"
"github.com/tango-contrib/xsrf"
)

type GroupAction struct {
BaseAction

get xweb.Mapper `xweb:"/"`
add xweb.Mapper
edit xweb.Mapper
del xweb.Mapper
type GroupBaseAction struct {
BaseAuthAction
}

func (c *GroupAction) Init() {
c.AddTmplVar("isCurModule", c.IsCurModule)
func (c *GroupBaseAction) Before() {
c.curModule = GROUP_MODULE
}

func (c *GroupAction) IsCurModule(module int) bool {
return GROUP_MODULE == module
type GroupAction struct {
GroupBaseAction
}

func (c *GroupAction) Get() error {
@@ -25,30 +23,42 @@ func (c *GroupAction) Get() error {
if err != nil {
return err
}
return c.Render("group/list.html", &xweb.T{
return c.Render("group/list.html", renders.T{
"groups": groups,
"admin": adminUser,
})
}

func (c *GroupAction) Add() error {
if c.Method() == "GET" {
return c.Render("group/add.html")
} else if c.Method() == "POST" {
name := c.GetString("name")
err := DB.AddGroup(name)
if err != nil {
return err
}
return c.Go("get")
type GroupAddAction struct {
GroupBaseAction
xsrf.Checker
}

func (c *GroupAddAction) Get() error {
return c.Render("group/add.html", renders.T{
"XsrfFormHtml": c.Checker.XsrfFormHtml(),
})
}

func (c *GroupAddAction) Post() error {
name := c.Form("name")
err := DB.AddGroup(name)
if err != nil {
return err
}
return xweb.NotSupported()
c.Redirect("/group")
return nil
}

func (c *GroupAction) Edit() error {
name := c.GetString("name")
type GroupEditAction struct {
GroupBaseAction
}

func (c *GroupEditAction) Get() error {
name := c.Form("name")
if name == "" {
return c.Go("get")
c.Redirect("/group")
return nil
}
var selUsers []string
err := DB.GroupUser(name, &selUsers)
@@ -73,17 +83,22 @@ func (c *GroupAction) Edit() error {
otherUsers = append(otherUsers, user.Name)
}
}
return c.Render("group/edit.html", &xweb.T{
return c.Render("group/edit.html", renders.T{
"selUsers": selUsers,
"otherUsers": otherUsers,
})
}

func (c *GroupAction) Del() error {
name := c.GetString("name")
type GroupDelAction struct {
GroupBaseAction
}

func (c *GroupDelAction) Get() error {
name := c.Form("name")
err := DB.DelGroup(name)
if err != nil {
return err
}
return c.Go("get")
c.Redirect("/group")
return nil
}

+ 58
- 30
web/perm.go View File

@@ -5,36 +5,28 @@ import (
"os"
"path"

"github.com/go-xweb/xweb"
"github.com/goftp/server"
"github.com/tango-contrib/renders"
)

type PermAction struct {
BaseAction

get xweb.Mapper `xweb:"/"`
add xweb.Mapper
edit xweb.Mapper
del xweb.Mapper
updateOwner xweb.Mapper
updateGroup xweb.Mapper
updatePerm xweb.Mapper
func hasPerm(mode os.FileMode, idx int, rOrW string) bool {
return string(mode.String()[idx]) == rOrW
}

func (c *PermAction) Init() {
c.AddTmplVar("isCurModule", c.IsCurModule)
type PermBaseAction struct {
BaseAuthAction
}

func (c *PermAction) IsCurModule(module int) bool {
return PERM_MODULE == module
func (c *PermBaseAction) Before() {
c.curModule = PERM_MODULE
}

func hasPerm(mode os.FileMode, idx int, rOrW string) bool {
return string(mode.String()[idx]) == rOrW
type PermAction struct {
PermBaseAction
}

func (c *PermAction) Get() error {
p := c.GetString("path")
p := c.Form("path")
var pathinfos = make([]server.FileInfo, 0)
var err error
var parent string
@@ -67,7 +59,7 @@ func (c *PermAction) Get() error {
if err != nil {
return err
}
return c.Render("perm/list.html", &xweb.T{
return c.Render("perm/list.html", renders.T{
"parent": parent,
"path": p,
"infos": pathinfos,
@@ -77,9 +69,37 @@ func (c *PermAction) Get() error {
})
}

func (c *PermAction) UpdateGroup() {
name := c.GetString("name")
newgroup := c.GetString("newgroup")
type PermAddAction struct {
PermBaseAction
}

func (p *PermAddAction) Get() error {
return nil
}

type PermEditAction struct {
PermBaseAction
}

func (p *PermEditAction) Get() error {
return nil
}

type PermDelAction struct {
PermBaseAction
}

func (p *PermDelAction) Get() error {
return nil
}

type PermUpdateGroup struct {
PermBaseAction
}

func (c *PermUpdateGroup) Get() {
name := c.Form("name")
newgroup := c.Form("newgroup")

if name == "" || newgroup == "" {
c.ServeJson(map[string]string{"status": "0", "error": "empty params"})
@@ -100,9 +120,13 @@ func (c *PermAction) UpdateGroup() {
c.ServeJson(map[string]string{"status": "1"})
}

func (c *PermAction) UpdateOwner() {
name := c.GetString("name")
newowner := c.GetString("newowner")
type PermUpdateOwner struct {
PermBaseAction
}

func (c *PermUpdateOwner) Get() {
name := c.Form("name")
newowner := c.Form("newowner")

if name == "" || newowner == "" {
c.ServeJson(map[string]string{"status": "0", "error": "empty params"})
@@ -123,11 +147,15 @@ func (c *PermAction) UpdateOwner() {
c.ServeJson(map[string]string{"status": "1"})
}

func (c *PermAction) UpdatePerm() {
name := c.GetString("name")
typ := c.GetString("typ")
right := c.GetString("right")
has := c.GetString("has")
type PermUpdatePerm struct {
PermBaseAction
}

func (c *PermUpdatePerm) Get() {
name := c.Form("name")
typ := c.Form("typ")
right := c.Form("right")
has := c.Form("has")

if name == "" || typ == "" || right == "" || has == "" {
c.ServeJson(map[string]string{"status": "0", "error": "empty params"})


+ 113
- 91
web/user.go View File

@@ -1,54 +1,20 @@
package web

import "github.com/go-xweb/xweb"
import (
"github.com/tango-contrib/renders"
"github.com/tango-contrib/xsrf"
)

type UserAction struct {
BaseAction

get xweb.Mapper `xweb:"/"`
add xweb.Mapper
edit xweb.Mapper
del xweb.Mapper
chgpass xweb.Mapper

module int
}

func (c *UserAction) Init() {
c.module = USER_MODULE
c.AddTmplVar("isCurModule", c.IsCurModule)
}

func (c *UserAction) IsCurModule(module int) bool {
return c.module == module
}

func (c *UserAction) Chgpass() error {
c.module = CHGPASS_MODULE
if c.Method() == "GET" {
user := c.GetSession("userId")
_, err := DB.GetUser(user.(string))
if err != nil {
return err
}

return c.Render("user/chgpass.html", &xweb.T{
"user": user,
})
} else if c.Method() == "POST" {
var user User
err := c.MapForm(&user, "")
if err != nil {
return err
}
err = DB.ChgPass(user.Name, user.Pass)
if err != nil {
return err
}
return c.Go("chgpass")
}
type UserBaseAction struct {
BaseAuthAction
}

return xweb.NotSupported()
func (c *UserBaseAction) Before() {
c.curModule = USER_MODULE
}

type UserAction struct {
UserBaseAction
}

func (a *UserAction) Get() error {
@@ -58,62 +24,118 @@ func (a *UserAction) Get() error {
return err
}

return a.Render("user/list.html", &xweb.T{
return a.Render("user/list.html", renders.T{
"users": users,
"admin": adminUser,
})
}

func (a *UserAction) Add() error {
if a.Method() == "GET" {
return a.Render("user/add.html")
} else if a.Method() == "POST" {
user := new(User)
err := a.MapForm(user, "")
if err != nil {
return err
}
err = DB.AddUser(user.Name, user.Pass)
if err != nil {
return err
}
return a.Go("get")
type ChgPassAction struct {
UserBaseAction
xsrf.Checker
}

func (c *ChgPassAction) Before() {
c.curModule = CHGPASS_MODULE
}

func (c *ChgPassAction) Get() error {
user := c.LoginUserId()
_, err := DB.GetUser(user)
if err != nil {
return err
}

return c.Render("user/chgpass.html", renders.T{
"user": user,
"userId": c.LoginUserId(),
"XsrfFormHtml": c.Checker.XsrfFormHtml(),
})
}

func (c *ChgPassAction) Post() error {
var user User
errs := c.Bind(&user)
if errs.Len() > 0 {
return errs[0]
}
err := DB.ChgPass(user.Name, user.Pass)
if err != nil {
return err
}
c.Redirect("/user/chgpass")
return nil
}

type UserAddAction struct {
UserBaseAction
xsrf.Checker
}

func (a *UserAddAction) Get() error {
return a.Render("user/add.html", renders.T{
"XsrfFormHtml": a.Checker.XsrfFormHtml(),
})
}

func (a *UserAddAction) Post() error {
var user User
errs := a.Bind(user)
if errs.Len() > 0 {
return errs[0]
}
err := DB.AddUser(user.Name, user.Pass)
if err != nil {
return err
}

a.Redirect("/user")
return nil
}

type UserEditAction struct {
UserBaseAction
xsrf.Checker
}

func (a *UserEditAction) Get() error {
name := a.Form("name")
pass, err := DB.GetUser(name)
if err != nil {
return err
}

return a.Render("user/edit.html", renders.T{
"user": &User{name, pass},
"XsrfFormHtml": a.Checker.XsrfFormHtml(),
})
}

func (a *UserEditAction) Post() error {
var user User
errs := a.Bind(&user)
if errs.Len() > 0 {
return errs[0]
}
return xweb.NotSupported()
}

func (a *UserAction) Edit() error {
if a.Method() == "GET" {
name := a.GetString("name")
pass, err := DB.GetUser(name)
if err != nil {
return err
}

return a.Render("user/edit.html", &xweb.T{
"user": &User{name, pass},
})
} else if a.Method() == "POST" {
user := new(User)
err := a.MapForm(user, "")
if err != nil {
return err
}
err = DB.ChgPass(user.Name, user.Pass)
if err != nil {
return err
}
return a.Go("get")
err := DB.ChgPass(user.Name, user.Pass)
if err != nil {
return err
}
return xweb.NotSupported()
a.Redirect("/user")
return nil
}

type UserDelAction struct {
UserBaseAction
}

func (a *UserAction) Del() error {
name := a.GetString("name")
func (a *UserDelAction) Get() error {
name := a.Form("name")
err := DB.DelUser(name)
if err != nil {
return err
}

return a.Go("get")
a.Redirect("/user")
return nil
}

+ 76
- 13
web/web.go View File

@@ -1,9 +1,15 @@
package web

import (
"github.com/go-xweb/xweb"
"time"

"github.com/goftp/server"
"github.com/lunny/tango"
"github.com/syndtr/goleveldb/leveldb"
"github.com/tango-contrib/binding"
"github.com/tango-contrib/renders"
"github.com/tango-contrib/session"
"github.com/tango-contrib/xsrf"
)

const (
@@ -20,7 +26,31 @@ var (
adminUser string
)

func Web(listen, static, templates, admin, pass string, ssl bool) {
type auther interface {
AskLogin() bool
IsLogin() bool
LoginUserId() string
}

func auth() tango.HandlerFunc {
return func(ctx *tango.Context) {
if a, ok := ctx.Action().(auther); ok {
if a.AskLogin() {
if !a.IsLogin() {
ctx.Redirect("/login")
return
}
}
}
ctx.Next()
}
}

const (
timeout = time.Minute * 20
)

func Web(listen, static, templates, admin, pass string, tls bool, certFile, keyFile string) {
_, err := DB.GetUser(admin)
if err != nil {
if err == leveldb.ErrNotFound {
@@ -32,18 +62,51 @@ func Web(listen, static, templates, admin, pass string, ssl bool) {
}
adminUser = admin

app := xweb.RootApp()
filter := xweb.NewLoginFilter(app, "userId", "/login")
filter.AddAnonymousUrls("/login")
app.AddFilter(filter)
t := tango.Classic()
t.Use(tango.Static(tango.StaticOptions{
RootPath: static,
}))
t.Use(renders.New(renders.Options{
Reload: true, // if reload when template is changed
Directory: templates,
}))
t.Use(session.New(session.Options{
MaxAge: timeout,
}))
t.Use(auth())
t.Use(binding.Bind())
t.Use(xsrf.New(timeout))

t.Get("/", new(MainAction))
t.Any("/login", new(LoginAction))
t.Get("/logout", new(LogoutAction))
t.Group("/user", func(g *tango.Group) {
g.Get("/", new(UserAction))
g.Any("/add", new(UserAddAction))
g.Any("/edit", new(UserEditAction))
g.Any("/del", new(UserDelAction))
})

xweb.SetStaticDir(static)
xweb.SetTemplateDir(templates)
xweb.AddAction(&MainAction{})
xweb.AutoAction(&UserAction{}, &GroupAction{}, &PermAction{})
t.Group("/group", func(g *tango.Group) {
g.Get("/", new(GroupAction))
g.Get("/add", new(GroupAddAction))
g.Get("/edit", new(GroupEditAction))
g.Get("/del", new(GroupDelAction))
})
t.Group("/perm", func(g *tango.Group) {
g.Get("/", new(PermAction))
g.Any("/add", new(PermAddAction))
g.Any("/edit", new(PermEditAction))
g.Any("/del", new(PermDelAction))
g.Any("/updateOwner", new(PermUpdateOwner))
g.Any("/updateGroup", new(PermUpdateGroup))
g.Any("/updatePerm", new(PermUpdatePerm))
})

if ssl {
//xweb.RunTLS(listen, config)
if tls {
t.RunTLS(certFile, keyFile, listen)
return
}
xweb.Run(listen)

t.Run(listen)
}

Loading…
Cancel
Save