Add user management interface
This commit is contained in:
parent
6cd5b1bc5e
commit
6f906ccae4
8 changed files with 124 additions and 8 deletions
|
@ -21,7 +21,9 @@ type DB interface {
|
|||
AddRawUser(name string, hpass []byte, salt []byte, role string) error
|
||||
GetRole(name string) (string, error)
|
||||
SetPassword(name string, pass string) error
|
||||
SetRole(name, role string) error
|
||||
ValidPassword(name string, pass string) bool
|
||||
ListUsers() ([]User, error)
|
||||
AddNews(text string) error
|
||||
AddRawNews(text string, date time.Time) error
|
||||
GetNews(num int, days int) (news []New, err error)
|
||||
|
@ -94,7 +96,7 @@ func (db pgDB) Close() error {
|
|||
}
|
||||
|
||||
func (db pgDB) create() error {
|
||||
models := []interface{}{&Book{}, &New{}, &user{}, &Visit{}, &Submission{}}
|
||||
models := []interface{}{&Book{}, &New{}, &User{}, &Visit{}, &Submission{}}
|
||||
for _, model := range models {
|
||||
options := &orm.CreateTableOptions{
|
||||
IfNotExists: true,
|
||||
|
|
|
@ -65,6 +65,14 @@ func (db *roDB) SetPassword(name string, pass string) error {
|
|||
return errors.New("RO database")
|
||||
}
|
||||
|
||||
func (db *roDB) SetRole(name, role string) error {
|
||||
return errors.New("RO database")
|
||||
}
|
||||
|
||||
func (db *roDB) ListUsers() ([]User, error) {
|
||||
return db.db.ListUsers()
|
||||
}
|
||||
|
||||
func (db *roDB) AddNews(text string) error {
|
||||
return errors.New("RO database")
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ import (
|
|||
"golang.org/x/crypto/scrypt"
|
||||
)
|
||||
|
||||
type user struct {
|
||||
type User struct {
|
||||
ID int `sql:"type:serial"`
|
||||
Username string `sql:"type:varchar(255),unique"`
|
||||
Password []byte
|
||||
|
@ -25,7 +25,7 @@ func (db *pgDB) AddUser(name string, pass string) error {
|
|||
if !validUserName(name) {
|
||||
return errors.New("Invalid user name")
|
||||
}
|
||||
num, err := db.sql.Model(&user{}).Where("lower(username) = lower(?)", name).Count()
|
||||
num, err := db.sql.Model(&User{}).Where("lower(username) = lower(?)", name).Count()
|
||||
if err != nil {
|
||||
log.Error("Error on database checking user ", name, ": ", err)
|
||||
return errors.New("An error happen on the database")
|
||||
|
@ -43,7 +43,7 @@ func (db *pgDB) AddUser(name string, pass string) error {
|
|||
}
|
||||
|
||||
func (db *pgDB) AddRawUser(name string, hpass []byte, salt []byte, role string) error {
|
||||
u := user{
|
||||
u := User{
|
||||
Username: name,
|
||||
Password: hpass,
|
||||
Salt: salt,
|
||||
|
@ -53,13 +53,21 @@ func (db *pgDB) AddRawUser(name string, hpass []byte, salt []byte, role string)
|
|||
}
|
||||
|
||||
func (db *pgDB) GetRole(name string) (string, error) {
|
||||
var u user
|
||||
var u User
|
||||
err := db.sql.Model(&u).Where("username = ?", name).Select()
|
||||
return u.Role, err
|
||||
}
|
||||
|
||||
func (db *pgDB) SetRole(name, role string) error {
|
||||
_, err := db.sql.Model(&User{}).
|
||||
Set("role = ?", role).
|
||||
Where("username = ?", name).
|
||||
Update()
|
||||
return err
|
||||
}
|
||||
|
||||
func (db *pgDB) ValidPassword(name string, pass string) bool {
|
||||
var u user
|
||||
var u User
|
||||
err := db.sql.Model(&u).Where("lower(username) = lower(?)", name).Select()
|
||||
if err != nil {
|
||||
return false
|
||||
|
@ -73,7 +81,7 @@ func (db *pgDB) ValidPassword(name string, pass string) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
_, err = db.sql.Model(&user{}).
|
||||
_, err = db.sql.Model(&User{}).
|
||||
Set("last_login = CURRENT_TIMESTAMP").
|
||||
Where("id = ?", u.ID).
|
||||
Update()
|
||||
|
@ -88,13 +96,19 @@ func (db *pgDB) SetPassword(name string, pass string) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = db.sql.Model(&user{}).
|
||||
_, err = db.sql.Model(&User{}).
|
||||
Set("password = ?, salt = ?", hash, salt).
|
||||
Where("username = ?", name).
|
||||
Update()
|
||||
return err
|
||||
}
|
||||
|
||||
func (db *pgDB) ListUsers() ([]User, error) {
|
||||
var users []User
|
||||
err := db.sql.Model(&users).Select()
|
||||
return users, err
|
||||
}
|
||||
|
||||
func validUserName(name string) bool {
|
||||
switch name {
|
||||
case "", "admin", "webmaster", "postmaster", "info", "root", "news":
|
||||
|
|
|
@ -73,6 +73,7 @@ func InitTemplate(assetsPath string) *Template {
|
|||
path.Join(templatePath, "dashboard.html"),
|
||||
path.Join(templatePath, "settings.html"),
|
||||
path.Join(templatePath, "help.html"),
|
||||
path.Join(templatePath, "user_admin.html"),
|
||||
))
|
||||
|
||||
t.rss = txt_tmpl.Must(txt_tmpl.ParseFiles(
|
||||
|
|
|
@ -196,6 +196,8 @@ func InitRouter(db database.DB, sg *StatsGatherer, assetsPath string) http.Handl
|
|||
r.HandleFunc("/edit/{id:"+idPattern+"}", sg.Gather(editHandler))
|
||||
r.HandleFunc("/store/{ids:(?:"+idPattern+"/)+}", sg.Gather(storeHandler))
|
||||
r.HandleFunc("/delete/{ids:(?:"+idPattern+"/)+}", sg.Gather(deleteHandler))
|
||||
r.HandleFunc("/admin/users/", sg.Gather(userAdminHandler)).Methods("GET")
|
||||
r.HandleFunc("/admin/users/", sg.Gather(userAdminPostHandler)).Methods("POST")
|
||||
|
||||
r.HandleFunc("/news/", sg.Gather(newsHandler))
|
||||
r.HandleFunc("/news/edit", sg.Gather(editNewsHandler)).Methods("GET")
|
||||
|
|
54
lib/user.go
54
lib/user.go
|
@ -2,6 +2,7 @@ package trantor
|
|||
|
||||
import (
|
||||
log "github.com/cihub/seelog"
|
||||
"gitlab.com/trantor/trantor/lib/database"
|
||||
|
||||
"net/http"
|
||||
)
|
||||
|
@ -95,3 +96,56 @@ func settingsHandler(h handler) {
|
|||
data.S.Title = "Settings -- " + data.S.Title
|
||||
h.load("settings", data)
|
||||
}
|
||||
|
||||
func userAdminHandler(h handler) {
|
||||
if !h.sess.IsAdmin() {
|
||||
notFound(h)
|
||||
return
|
||||
}
|
||||
|
||||
users, err := h.db.ListUsers()
|
||||
if err != nil {
|
||||
log.Error("Something went wrong listing users: ", err)
|
||||
notFound(h)
|
||||
return
|
||||
}
|
||||
|
||||
var data userAdminData
|
||||
data.S = GetStatus(h)
|
||||
data.S.Title = "Users admin -- " + data.S.Title
|
||||
data.Users = users
|
||||
h.load("user_admin", data)
|
||||
}
|
||||
|
||||
func userAdminPostHandler(h handler) {
|
||||
if !h.sess.IsAdmin() {
|
||||
notFound(h)
|
||||
return
|
||||
}
|
||||
|
||||
username := h.r.FormValue("username")
|
||||
password := h.r.FormValue("password")
|
||||
role := h.r.FormValue("role")
|
||||
if password != "" {
|
||||
err := h.db.SetPassword(username, password)
|
||||
if err != nil {
|
||||
h.sess.Notify("An error ocurred!", err.Error(), "error")
|
||||
} else {
|
||||
h.sess.Notify("Password updated!", "", "success")
|
||||
}
|
||||
} else if role != "" {
|
||||
err := h.db.SetRole(username, role)
|
||||
if err != nil {
|
||||
h.sess.Notify("An error ocurred!", err.Error(), "error")
|
||||
} else {
|
||||
h.sess.Notify("Role updated!", "", "success")
|
||||
}
|
||||
}
|
||||
|
||||
userAdminHandler(h)
|
||||
}
|
||||
|
||||
type userAdminData struct {
|
||||
S Status
|
||||
Users []database.User
|
||||
}
|
||||
|
|
|
@ -72,6 +72,7 @@
|
|||
<li><a href="/new/"><i class="icon-book"></i> New books</a></li>
|
||||
{{if eq .Role "admin"}}
|
||||
<li><a href="/news/edit"><i class="icon-certificate"></i> Edit news</a></li>
|
||||
<li><a href="/admin/users/"><i class="icon-user"></i> Users admin</a></li>
|
||||
{{end}}
|
||||
<li class="divider"></li>
|
||||
{{end}}
|
||||
|
|
34
templates/user_admin.html
Normal file
34
templates/user_admin.html
Normal file
|
@ -0,0 +1,34 @@
|
|||
{{template "header.html" .S}}
|
||||
|
||||
<h4>Users:</h4>
|
||||
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<th>username</th>
|
||||
<th>role</th>
|
||||
<th>password</th>
|
||||
<th>last login</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{range .Users}}
|
||||
<tr>
|
||||
<td>{{.Username}}</td>
|
||||
<td><form class="row form-inline" method="POST" action="/admin/users/">
|
||||
<input type="hidden" id="username" name="username" value="{{.Username}}">
|
||||
<input type="text" id="role" name="role" value="{{.Role}}">
|
||||
<button type="submit" class="btn btn-primary">Update</button>
|
||||
</form>
|
||||
</td>
|
||||
<td><form class="row form-inline" method="POST" action="/admin/users/">
|
||||
<input type="hidden" id="username" name="username" value="{{.Username}}">
|
||||
<input type="password" id="password" name="password" placeholder="password">
|
||||
<button type="submit" class="btn btn-primary">Update</button>
|
||||
</form>
|
||||
</td>
|
||||
<td>{{.LastLogin.Format "2006-01-02"}}</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
{{template "footer.html"}}
|
Reference in a new issue