Sessions with gorilla
This commit is contained in:
parent
44114bd91d
commit
c513344169
15 changed files with 251 additions and 47 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -7,3 +7,4 @@ upload/upload
|
||||||
upload/books
|
upload/books
|
||||||
upload/cover
|
upload/cover
|
||||||
upload/new
|
upload/new
|
||||||
|
adduser/adduser
|
||||||
|
|
30
admin.go
Normal file
30
admin.go
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"labix.org/v2/mgo"
|
||||||
|
"labix.org/v2/mgo/bson"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func deleteHandler(coll *mgo.Collection) func(http.ResponseWriter, *http.Request) {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if SessionUser(r) == "" {
|
||||||
|
http.NotFound(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var id bson.ObjectId = bson.ObjectIdHex(r.URL.Path[len("/delete/"):])
|
||||||
|
var book Book
|
||||||
|
if coll.Find(bson.M{"_id": id}).One(&book) != nil {
|
||||||
|
http.NotFound(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
os.RemoveAll(book.Path)
|
||||||
|
os.RemoveAll(book.Cover[1:])
|
||||||
|
os.RemoveAll(book.CoverSmall[1:])
|
||||||
|
coll.Remove(bson.M{"_id": id})
|
||||||
|
http.Redirect(w, r, "/", 307)
|
||||||
|
//TODO: notify deleted
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
type Book struct {
|
type Book struct {
|
||||||
|
Id string `bson:"_id"`
|
||||||
Title string
|
Title string
|
||||||
Author []string
|
Author []string
|
||||||
Contributor string
|
Contributor string
|
||||||
|
|
|
@ -31,7 +31,7 @@ func buildQuery(q string) bson.M {
|
||||||
}
|
}
|
||||||
|
|
||||||
type searchData struct {
|
type searchData struct {
|
||||||
Search string
|
S Status
|
||||||
Found int
|
Found int
|
||||||
Books []Book
|
Books []Book
|
||||||
Page int
|
Page int
|
||||||
|
@ -59,7 +59,8 @@ func searchHandler(coll *mgo.Collection) func(http.ResponseWriter, *http.Request
|
||||||
}
|
}
|
||||||
|
|
||||||
var data searchData
|
var data searchData
|
||||||
data.Search = req
|
data.S.User = SessionUser(r)
|
||||||
|
data.S.Search = req
|
||||||
data.Found = len(res)
|
data.Found = len(res)
|
||||||
if len(res) > ITEMS_PAGE*(page+1) {
|
if len(res) > ITEMS_PAGE*(page+1) {
|
||||||
data.Books = res[ITEMS_PAGE*page : ITEMS_PAGE*(page+1)]
|
data.Books = res[ITEMS_PAGE*page : ITEMS_PAGE*(page+1)]
|
||||||
|
|
43
session.go
Normal file
43
session.go
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"code.google.com/p/gorilla/sessions"
|
||||||
|
"code.google.com/p/gorilla/securecookie"
|
||||||
|
)
|
||||||
|
|
||||||
|
var sesStore = sessions.NewCookieStore(securecookie.GenerateRandomKey(64))
|
||||||
|
|
||||||
|
func CreateSession(user string, w http.ResponseWriter, r *http.Request) {
|
||||||
|
session, _ := sesStore.Get(r, "admin")
|
||||||
|
session.Values["user"] = user
|
||||||
|
session.Save(r, w)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SessionUser(r *http.Request) string {
|
||||||
|
session, err := sesStore.New(r, "admin")
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if session.IsNew {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
user, ok := session.Values["user"].(string)
|
||||||
|
if !ok {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return user
|
||||||
|
}
|
||||||
|
|
||||||
|
func LogOut(w http.ResponseWriter, r *http.Request) {
|
||||||
|
session, err := sesStore.Get(r, "admin")
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if session.IsNew {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
session.Values["user"] = ""
|
||||||
|
session.Options.MaxAge = -1
|
||||||
|
session.Save(r, w)
|
||||||
|
}
|
|
@ -9,6 +9,14 @@ const (
|
||||||
TEMPLATE_DIR = "templates/"
|
TEMPLATE_DIR = "templates/"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type Status struct {
|
||||||
|
Search string
|
||||||
|
User string
|
||||||
|
Home bool
|
||||||
|
About bool
|
||||||
|
Upload bool
|
||||||
|
}
|
||||||
|
|
||||||
func loadTemplate(w http.ResponseWriter, tmpl string, data interface{}) {
|
func loadTemplate(w http.ResponseWriter, tmpl string, data interface{}) {
|
||||||
// TODO: when finish devel conver to global:
|
// TODO: when finish devel conver to global:
|
||||||
var templates = template.Must(template.ParseFiles(TEMPLATE_DIR+"header.html",
|
var templates = template.Must(template.ParseFiles(TEMPLATE_DIR+"header.html",
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{{template "header.html"}}
|
{{template "header.html" .S}}
|
||||||
|
|
||||||
<p>The <strong>Imperial Library of Trantor</strong> (also known as <em>Galactic Library</em>) is a repository of ebooks on ePub format.</p>
|
<p>The <strong>Imperial Library of Trantor</strong> (also known as <em>Galactic Library</em>) is a repository of ebooks on ePub format.</p>
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,27 @@
|
||||||
{{template "header.html"}}
|
{{template "header.html" .S}}
|
||||||
|
|
||||||
<div class="row">
|
{{$user := .S.User}}
|
||||||
|
{{with .Book}}
|
||||||
|
<script>
|
||||||
|
function delBook(){
|
||||||
|
var div = document.getElementById('delete');
|
||||||
|
div.innerHTML =
|
||||||
|
'<div class="alert alert-error fade in"> \
|
||||||
|
<a class="close" data-dismiss="alert">×</a> \
|
||||||
|
<h4 class="alert-heading">Do you really want to delete it?</h4> \
|
||||||
|
<p>Remove a book is permanent, you won\'t be able to get it back</p> \
|
||||||
|
<a class="btn btn-danger" href="/delete/{{.Id}}">Remove it</a> \
|
||||||
|
<a class="btn" href="#" data-dismiss="alert">Cancel</a> \
|
||||||
|
</div>';
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<div id="delete"></div>
|
||||||
|
|
||||||
|
<header class="row">
|
||||||
<div class="span8 offset4">
|
<div class="span8 offset4">
|
||||||
<h1>{{.Title}}</h1>
|
<h1>{{.Title}}</h1>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</header>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
{{if .Cover}}
|
{{if .Cover}}
|
||||||
<div class="span4">
|
<div class="span4">
|
||||||
|
@ -15,7 +32,7 @@
|
||||||
<div class="span8">
|
<div class="span8">
|
||||||
<div class="row"><p></p></div>
|
<div class="row"><p></p></div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="span4">
|
<div class="span6">
|
||||||
<ul class="unstyled">
|
<ul class="unstyled">
|
||||||
{{if .Author}}<li><strong>Author:</strong> {{range .Author}}<a href="/search/?q=author:{{.}}">{{.}}</a>, {{end}}</li>{{end}}
|
{{if .Author}}<li><strong>Author:</strong> {{range .Author}}<a href="/search/?q=author:{{.}}">{{.}}</a>, {{end}}</li>{{end}}
|
||||||
{{if .Publisher}}<li><strong>Publisher:</strong> <a href="/search/?q=publisher:{{.Publisher}}">{{.Publisher}}</a></li>{{end}}
|
{{if .Publisher}}<li><strong>Publisher:</strong> <a href="/search/?q=publisher:{{.Publisher}}">{{.Publisher}}</a></li>{{end}}
|
||||||
|
@ -24,8 +41,19 @@
|
||||||
{{if .Lang}}<li><strong>Lang:</strong> {{range .Lang}}<a href="/search/?q=lang:{{.}}">{{.}}</a> {{end}}</li>{{end}}
|
{{if .Lang}}<li><strong>Lang:</strong> {{range .Lang}}<a href="/search/?q=lang:{{.}}">{{.}}</a> {{end}}</li>{{end}}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="span4">
|
<div class="span2">
|
||||||
|
{{if $user}}
|
||||||
|
<div class="row">
|
||||||
|
<div class="btn-group pull-right">
|
||||||
|
<a href="/edit/{{.Id}}" class="btn btn-primary"><i class="icon-pencil"></i> Edit</a>
|
||||||
|
<a href="#" onClick="delBook();" class="btn btn-danger"><i class="icon-trash"></i> Delete</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row"><p></p></div>
|
||||||
|
{{end}}
|
||||||
|
<div class="row">
|
||||||
<p><a href="/{{.Path}}" class="btn btn-large btn-inverse pull-right"><i class="icon-download-alt icon-white"></i> download</a></p>
|
<p><a href="/{{.Path}}" class="btn btn-large btn-inverse pull-right"><i class="icon-download-alt icon-white"></i> download</a></p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -35,7 +63,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
{{end}}
|
||||||
|
|
||||||
{{template "footer.html"}}
|
{{template "footer.html"}}
|
||||||
|
|
|
@ -7,17 +7,8 @@
|
||||||
|
|
||||||
<!-- Placed at the end of the document so the pages load faster -->
|
<!-- Placed at the end of the document so the pages load faster -->
|
||||||
<script src="/js/jquery.js"></script>
|
<script src="/js/jquery.js"></script>
|
||||||
<script src="/js/bootstrap-transition.js"></script>
|
|
||||||
<script src="/js/bootstrap-alert.js"></script>
|
|
||||||
<script src="/js/bootstrap-modal.js"></script>
|
<script src="/js/bootstrap-modal.js"></script>
|
||||||
<script src="/js/bootstrap-dropdown.js"></script>
|
<script src="/js/bootstrap-dropdown.js"></script>
|
||||||
<script src="/js/bootstrap-scrollspy.js"></script>
|
<script src="/js/bootstrap-alert.js"></script>
|
||||||
<script src="/js/bootstrap-tab.js"></script>
|
|
||||||
<script src="/js/bootstrap-tooltip.js"></script>
|
|
||||||
<script src="/js/bootstrap-popover.js"></script>
|
|
||||||
<script src="/js/bootstrap-button.js"></script>
|
|
||||||
<script src="/js/bootstrap-collapse.js"></script>
|
|
||||||
<script src="/js/bootstrap-carousel.js"></script>
|
|
||||||
<script src="/js/bootstrap-typeahead.js"></script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -9,24 +9,72 @@
|
||||||
<title>Imperial Library of Trantor</title>
|
<title>Imperial Library of Trantor</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<!-- login screen -->
|
||||||
|
<div class="modal hide" id="login">
|
||||||
|
<div class="modal-header">
|
||||||
|
<a type="button" class="close" data-dismiss="modal">×</a>
|
||||||
|
<h3>Log In</h3>
|
||||||
|
</div>
|
||||||
|
<form class="form-horizontal" method="POST" action="/login/" enctype="application/x-www-form-urlencoded">
|
||||||
|
<div class="modal-body">
|
||||||
|
<fieldset>
|
||||||
|
<div class="control-group">
|
||||||
|
<div class="controls">
|
||||||
|
<div class="input-prepend">
|
||||||
|
<div class="add-on"><i class="icon-user"></i></div>
|
||||||
|
<input style="height:28px;" type="text" placeholder="Username" size="16" name="user" autofocus="autofocus">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="control-group">
|
||||||
|
<div class="controls">
|
||||||
|
<div class="input-prepend">
|
||||||
|
<div class="add-on"><i class="icon-lock"></i></div>
|
||||||
|
<input style="height:28px;" type="password" placeholder="Password" size="16" name="pass">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<fieldset>
|
||||||
|
<a href="#" class="btn" data-dismiss="modal">Cancel</a>
|
||||||
|
<input class="btn btn-primary" type="submit" name="submit" value="Log In"/>
|
||||||
|
</fieldset>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="navbar">
|
<div class="navbar">
|
||||||
<div class="navbar-inner">
|
<div class="navbar-inner">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
|
|
||||||
<span class="icon-bar"></span>
|
|
||||||
<span class="icon-bar"></span>
|
|
||||||
<span class="icon-bar"></span>
|
|
||||||
</a>
|
|
||||||
<a class="brand" href="/">Imperial Library</a>
|
<a class="brand" href="/">Imperial Library</a>
|
||||||
<div class="nav-collapse">
|
<div class="nav-collapse">
|
||||||
<ul class="nav">
|
<ul class="nav">
|
||||||
<li><a href="/">Home</a></li>
|
<li {{if .Home}}class="active"{{end}}><a href="/">Home</a></li>
|
||||||
<li><a href="/about/">About</a></li>
|
<li {{if .About}}class="active"{{end}}><a href="/about/">About</a></li>
|
||||||
<li><a href="/upload/">Upload your epub</a></li>
|
<li {{if .Upload}}class="active"{{end}}><a href="/upload/">Upload your epub</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<ul class="nav pull-right">
|
||||||
|
<li class="divider-vertical"></li>
|
||||||
|
{{if .User}}
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
|
||||||
|
<i class="icon-user icon-white"></i> {{.User}}<b class="caret"></b>
|
||||||
|
</a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li class="divider"></li>
|
||||||
|
<li><a href="/logout/"><i class="icon-off"></i> Log Out</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
{{else}}
|
||||||
|
<li><a data-toggle="modal" href="#login"><i class="icon-share-alt icon-white"></i></a></li>
|
||||||
|
{{end}}
|
||||||
</ul>
|
</ul>
|
||||||
</div><!--/.nav-collapse -->
|
</div><!--/.nav-collapse -->
|
||||||
<form class="navbar-search pull-right" action="/search/">
|
<form class="navbar-search pull-right" action="/search/">
|
||||||
<input type="search" class="search-query span3" name="q" {{if .}}value="{{.}}"{{else}}placeholder="Search"{{end}} />
|
<input type="search" class="search-query span3" name="q" {{if .Search}}value="{{.Search}}"{{else}}placeholder="Search"{{end}} />
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,10 +1,4 @@
|
||||||
{{template "header.html"}}
|
{{template "header.html" .S}}
|
||||||
|
|
||||||
<!--<p><img src="/img/library.jpg" alt="library" /></p>
|
|
||||||
<form action="/search/">
|
|
||||||
<input type="search" name="q" />
|
|
||||||
<input type="submit" value="Search">
|
|
||||||
</form>-->
|
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="span8">
|
<div class="span8">
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{{template "header.html" .Search}}
|
{{template "header.html" .S}}
|
||||||
|
|
||||||
<p class="centered">Found {{.Found}} books. Page {{.Page}}</p>
|
<p class="centered">Found {{.Found}} books. Page {{.Page}}</p>
|
||||||
|
|
||||||
|
@ -18,10 +18,10 @@
|
||||||
{{with .Books}}
|
{{with .Books}}
|
||||||
{{range .}}
|
{{range .}}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="span2">
|
<div class="span1">
|
||||||
<p class="pull-right"><a href="/book/{{.Title}}">{{if .CoverSmall}}<img src="{{.CoverSmall}}" alt="{{.Title}}" />{{end}}</a></p>
|
<p class="pull-right"><a href="/book/{{.Title}}">{{if .CoverSmall}}<img src="{{.CoverSmall}}" alt="{{.Title}}" />{{end}}</a></p>
|
||||||
</div>
|
</div>
|
||||||
<div class="span10">
|
<div class="span11">
|
||||||
<p class="well"><a href="/book/{{.Title}}"><strong>{{.Title}}</strong></a><br />
|
<p class="well"><a href="/book/{{.Title}}"><strong>{{.Title}}</strong></a><br />
|
||||||
{{range .Author}}{{.}}, {{end}}</p>
|
{{range .Author}}{{.}}, {{end}}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{{template "header.html"}}
|
{{template "header.html" .S}}
|
||||||
|
|
||||||
{{if .}}<p>{{.}}</p>{{end}}
|
{{if .Msg}}<p>{{.Msg}}</p>{{end}}
|
||||||
|
|
||||||
<form method="POST" enctype="multipart/form-data">
|
<form method="POST" enctype="multipart/form-data">
|
||||||
<input accept="application/epub+zip" type="file" name="epub" />
|
<input accept="application/epub+zip" type="file" name="epub" />
|
||||||
|
|
59
trantor.go
59
trantor.go
|
@ -1,6 +1,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/md5"
|
||||||
"labix.org/v2/mgo"
|
"labix.org/v2/mgo"
|
||||||
"labix.org/v2/mgo/bson"
|
"labix.org/v2/mgo/bson"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -10,17 +11,60 @@ const (
|
||||||
IP = "127.0.0.1"
|
IP = "127.0.0.1"
|
||||||
DB_NAME = "trantor"
|
DB_NAME = "trantor"
|
||||||
BOOKS_COLL = "books"
|
BOOKS_COLL = "books"
|
||||||
|
USERS_COLL = "users"
|
||||||
|
PASS_SALT = "ImperialLibSalt"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type aboutData struct {
|
||||||
|
S Status
|
||||||
|
}
|
||||||
|
|
||||||
func aboutHandler(w http.ResponseWriter, r *http.Request) {
|
func aboutHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
loadTemplate(w, "about", nil)
|
var data aboutData
|
||||||
|
data.S.User = SessionUser(r)
|
||||||
|
data.S.About = true
|
||||||
|
loadTemplate(w, "about", data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func logoutHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
LogOut(w, r)
|
||||||
|
http.Redirect(w, r, "/", 307)
|
||||||
|
}
|
||||||
|
|
||||||
|
func loginHandler(coll *mgo.Collection) func(http.ResponseWriter, *http.Request) {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if r.Method == "POST" {
|
||||||
|
user := r.FormValue("user")
|
||||||
|
pass := r.FormValue("pass")
|
||||||
|
h := md5.New()
|
||||||
|
hash := h.Sum(([]byte)(PASS_SALT + pass))
|
||||||
|
n, _ := coll.Find(bson.M{"user":user, "pass":hash}).Count()
|
||||||
|
if n != 0 {
|
||||||
|
// TODO: display success
|
||||||
|
CreateSession(user, w, r)
|
||||||
|
} else {
|
||||||
|
// TODO: display error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
http.Redirect(w, r, "/", 307)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type bookData struct {
|
||||||
|
S Status
|
||||||
|
Book Book
|
||||||
}
|
}
|
||||||
|
|
||||||
func bookHandler(coll *mgo.Collection) func(http.ResponseWriter, *http.Request) {
|
func bookHandler(coll *mgo.Collection) func(http.ResponseWriter, *http.Request) {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
var book Book
|
var data bookData
|
||||||
coll.Find(bson.M{"title": r.URL.Path[len("/book/"):]}).One(&book)
|
data.S.User = SessionUser(r)
|
||||||
loadTemplate(w, "book", book)
|
if coll.Find(bson.M{"title": r.URL.Path[len("/book/"):]}).One(&data.Book) != nil {
|
||||||
|
http.NotFound(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
data.Book.Id = bson.ObjectId(data.Book.Id).Hex()
|
||||||
|
loadTemplate(w, "book", data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,6 +74,7 @@ func fileHandler(path string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type indexData struct {
|
type indexData struct {
|
||||||
|
S Status
|
||||||
Books []Book
|
Books []Book
|
||||||
Count int
|
Count int
|
||||||
}
|
}
|
||||||
|
@ -37,6 +82,8 @@ type indexData struct {
|
||||||
func indexHandler(coll *mgo.Collection) func(http.ResponseWriter, *http.Request) {
|
func indexHandler(coll *mgo.Collection) func(http.ResponseWriter, *http.Request) {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
var data indexData
|
var data indexData
|
||||||
|
data.S.User = SessionUser(r)
|
||||||
|
data.S.Home = true
|
||||||
data.Count, _ = coll.Count()
|
data.Count, _ = coll.Count()
|
||||||
coll.Find(bson.M{}).Sort("-_id").Limit(6).All(&data.Books)
|
coll.Find(bson.M{}).Sort("-_id").Limit(6).All(&data.Books)
|
||||||
loadTemplate(w, "index", data)
|
loadTemplate(w, "index", data)
|
||||||
|
@ -50,10 +97,14 @@ func main() {
|
||||||
}
|
}
|
||||||
defer session.Close()
|
defer session.Close()
|
||||||
coll := session.DB(DB_NAME).C(BOOKS_COLL)
|
coll := session.DB(DB_NAME).C(BOOKS_COLL)
|
||||||
|
userColl := session.DB(DB_NAME).C(USERS_COLL)
|
||||||
|
|
||||||
http.HandleFunc("/book/", bookHandler(coll))
|
http.HandleFunc("/book/", bookHandler(coll))
|
||||||
http.HandleFunc("/search/", searchHandler(coll))
|
http.HandleFunc("/search/", searchHandler(coll))
|
||||||
http.HandleFunc("/upload/", uploadHandler(coll))
|
http.HandleFunc("/upload/", uploadHandler(coll))
|
||||||
|
http.HandleFunc("/login/", loginHandler(userColl))
|
||||||
|
http.HandleFunc("/logout/", logoutHandler)
|
||||||
|
http.HandleFunc("/delete/", deleteHandler(coll))
|
||||||
http.HandleFunc("/about/", aboutHandler)
|
http.HandleFunc("/about/", aboutHandler)
|
||||||
fileHandler("/img/")
|
fileHandler("/img/")
|
||||||
fileHandler("/cover/")
|
fileHandler("/cover/")
|
||||||
|
|
14
upload.go
14
upload.go
|
@ -42,18 +42,26 @@ func storeFile(r *http.Request) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type uploadData struct {
|
||||||
|
S Status
|
||||||
|
Msg string
|
||||||
|
}
|
||||||
|
|
||||||
func uploadHandler(coll *mgo.Collection) func(http.ResponseWriter, *http.Request) {
|
func uploadHandler(coll *mgo.Collection) func(http.ResponseWriter, *http.Request) {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
status := ""
|
var data uploadData
|
||||||
|
data.S.User = SessionUser(r)
|
||||||
|
data.S.Upload = true
|
||||||
|
data.Msg = ""
|
||||||
if r.Method == "POST" {
|
if r.Method == "POST" {
|
||||||
err := storeFile(r)
|
err := storeFile(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
status = "Upload successful."
|
data.Msg = "Upload successful."
|
||||||
}
|
}
|
||||||
|
|
||||||
loadTemplate(w, "upload", status)
|
loadTemplate(w, "upload", data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue