Allow edit user info
This commit is contained in:
parent
b4bb23056b
commit
0e2733086e
19
auth/auth.go
19
auth/auth.go
@ -91,6 +91,25 @@ func (a *Authorizer) Login(rw http.ResponseWriter, req *http.Request, username,
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *Authorizer) RegenSecret(user User, w http.ResponseWriter, r *http.Request) error {
|
||||
cookie, err := a.cookiejar.Get(r, a.cookieName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// genereate secret
|
||||
b, err := bcrypt.GenerateFromPassword([]byte(user.GetHash()), a.cost)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cookie.Values["secret"] = string(b)
|
||||
|
||||
err = cookie.Save(r, w)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Logout remove cookie info
|
||||
func (a *Authorizer) Logout(rw http.ResponseWriter, req *http.Request) error {
|
||||
cookie, err := a.cookiejar.Get(req, a.cookieName)
|
||||
|
17
main.go
17
main.go
@ -1,8 +1,6 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"gitlab.quimbo.fr/odwrtw/canape-sql/auth"
|
||||
"gitlab.quimbo.fr/odwrtw/canape-sql/movies"
|
||||
"gitlab.quimbo.fr/odwrtw/canape-sql/users"
|
||||
@ -28,8 +26,7 @@ func main() {
|
||||
pgdsn := "postgres://test:test@127.0.0.1:5432/test?sslmode=disable"
|
||||
db, err := sqlx.Connect("postgres", pgdsn)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
os.Exit(1)
|
||||
log.Panic(err)
|
||||
}
|
||||
uBackend := &UserBackend{db}
|
||||
authorizer := auth.New(uBackend, "peeper", "cookieName", "cookieKey", 10)
|
||||
@ -37,16 +34,16 @@ func main() {
|
||||
env := web.NewEnv(db, authorizer, log, "./templates")
|
||||
authMiddleware := auth.NewMiddleware(env.Auth)
|
||||
|
||||
env.Handle("users.login", "/users/login", users.LoginHandler)
|
||||
env.Handle("users.logout", "/users/logout", users.LogoutHandler)
|
||||
env.HandleRole("users.details", "/users/details", users.DetailsHandler, users.UserRole)
|
||||
env.Handle("users.login", "/users/login", users.Login)
|
||||
env.Handle("users.logout", "/users/logout", users.Logout)
|
||||
env.HandleRole("users.details", "/users/details", users.Details, users.UserRole)
|
||||
env.HandleRole("users.edit", "/users/edit", users.Edit, users.UserRole)
|
||||
|
||||
env.HandleRole("movies.polochon", "/", movies.PolochonMovies, users.UserRole)
|
||||
env.HandleRole("movies.polochon", "/movies/polochon", movies.FromPolochon, users.UserRole)
|
||||
|
||||
err = env.SetLoginRoute("users.login")
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
os.Exit(1)
|
||||
log.Panic(err)
|
||||
}
|
||||
|
||||
n := negroni.Classic()
|
||||
|
@ -14,7 +14,7 @@ import (
|
||||
"gitlab.quimbo.fr/odwrtw/papi"
|
||||
)
|
||||
|
||||
func PolochonMovies(env *web.Env, w http.ResponseWriter, r *http.Request) error {
|
||||
func FromPolochon(env *web.Env, w http.ResponseWriter, r *http.Request) error {
|
||||
|
||||
v := auth.GetCurrentUser(r)
|
||||
user, ok := v.(*users.User)
|
||||
|
26
templates/users/details.tmpl
Normal file
26
templates/users/details.tmpl
Normal file
@ -0,0 +1,26 @@
|
||||
<div class="container">
|
||||
<div id="user-details" class="content-fluid">
|
||||
|
||||
<div class="col-md-6 col-md-offset-3 col-xs-12">
|
||||
<h2>{{ $.Data.user.Name }}'s informations</h2>
|
||||
<hr>
|
||||
|
||||
<div class="panel panel-info">
|
||||
<div class="panel-heading">
|
||||
Polochon URL
|
||||
</div>
|
||||
<div class="panel-body">{{ $.Data.polochon.URL }}</div>
|
||||
</div>
|
||||
<div class="panel panel-info">
|
||||
<div class="panel-heading">
|
||||
Polochon token
|
||||
</div>
|
||||
<div class="panel-body">{{ $.Data.polochon.Token }}</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<a class="btn btn-default pull-left" href="{{ URL "users.edit" }}">Edit</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
43
templates/users/edit.tmpl
Normal file
43
templates/users/edit.tmpl
Normal file
@ -0,0 +1,43 @@
|
||||
|
||||
<div class="container">
|
||||
<div class="content-fluid">
|
||||
<div class="col-md-6 col-md-offset-3 col-xs-12">
|
||||
<h2>Edit user</h2>
|
||||
<hr>
|
||||
|
||||
<form accept-charset="UTF-8" action="{{ URL "users.edit" }}" method="POST" class="form-horizontal" id="user">
|
||||
|
||||
<div class="form-group">
|
||||
<label class="control-label" for="PolochonURL">Polochon URL</label>
|
||||
<input autofocus="autofocus" class="form-control" name="PolochonURL" type="text" value="{{ $.Data.polochon.URL }}">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="control-label" for="PolochonToken">Polochon token</label>
|
||||
<input autofocus="autofocus" class="form-control" name="PolochonToken" type="text" value="{{ $.Data.polochon.Token }}" >
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="control-label" for="Password">Password</label>
|
||||
<input autocomplete="off" class="form-control" name="Password" type="password" value="">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="control-label" for="PasswordVerify">Confirm Password</label>
|
||||
<input autocomplete="off" class="form-control" name="PasswordVerify" type="password" value="">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<input class="btn btn-primary pull-right" type="submit" value="Update">
|
||||
<a class="btn btn-default pull-left" href="{{ URL "users.details" }}">Cancel</a>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -5,12 +5,15 @@ import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gorilla/Schema"
|
||||
"github.com/kr/pretty"
|
||||
|
||||
"gitlab.quimbo.fr/odwrtw/canape-sql/auth"
|
||||
"gitlab.quimbo.fr/odwrtw/canape-sql/config"
|
||||
"gitlab.quimbo.fr/odwrtw/canape-sql/web"
|
||||
)
|
||||
|
||||
func LoginHandler(e *web.Env, w http.ResponseWriter, r *http.Request) error {
|
||||
// Login login user
|
||||
func Login(e *web.Env, w http.ResponseWriter, r *http.Request) error {
|
||||
if r.Method == "GET" {
|
||||
return e.Rends(w, r, "users/login")
|
||||
}
|
||||
@ -53,21 +56,101 @@ func LoginHandler(e *web.Env, w http.ResponseWriter, r *http.Request) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func LogoutHandler(e *web.Env, w http.ResponseWriter, r *http.Request) error {
|
||||
// Logout just logout
|
||||
func Logout(e *web.Env, w http.ResponseWriter, r *http.Request) error {
|
||||
e.Auth.Logout(w, r)
|
||||
route := e.GetLoginRouteGetter()()
|
||||
http.Redirect(w, r, route, http.StatusTemporaryRedirect)
|
||||
return nil
|
||||
}
|
||||
|
||||
func DetailsHandler(e *web.Env, w http.ResponseWriter, r *http.Request) error {
|
||||
u := auth.GetCurrentUser(r)
|
||||
if u == nil {
|
||||
return nil
|
||||
}
|
||||
_, ok := u.(*User)
|
||||
// Details show user details
|
||||
func Details(env *web.Env, w http.ResponseWriter, r *http.Request) error {
|
||||
v := auth.GetCurrentUser(r)
|
||||
user, ok := v.(*User)
|
||||
if !ok {
|
||||
return fmt.Errorf("Invalid user type")
|
||||
return fmt.Errorf("invalid user type")
|
||||
}
|
||||
return nil
|
||||
|
||||
var polochonConfig config.UserPolochon
|
||||
err := user.GetConfig("polochon", &polochonConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
web.SetData(r, "user", user)
|
||||
web.SetData(r, "polochon", polochonConfig)
|
||||
return env.Rends(w, r, "users/details")
|
||||
}
|
||||
|
||||
// Edit allow editing user info and configuration
|
||||
func Edit(env *web.Env, w http.ResponseWriter, r *http.Request) error {
|
||||
v := auth.GetCurrentUser(r)
|
||||
user, ok := v.(*User)
|
||||
if !ok {
|
||||
return fmt.Errorf("invalid user type")
|
||||
}
|
||||
var polochonConfig config.UserPolochon
|
||||
err := user.GetConfig("polochon", &polochonConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if r.Method == "GET" {
|
||||
web.SetData(r, "user", user)
|
||||
web.SetData(r, "polochon", polochonConfig)
|
||||
return env.Rends(w, r, "users/edit")
|
||||
}
|
||||
|
||||
type editForm struct {
|
||||
PolochonURL string
|
||||
PolochonToken string
|
||||
Password string
|
||||
PasswordVerify string
|
||||
}
|
||||
|
||||
err = r.ParseForm()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
form := new(editForm)
|
||||
decoder := schema.NewDecoder()
|
||||
err = decoder.Decode(form, r.PostForm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
polochonConfig.URL = form.PolochonURL
|
||||
polochonConfig.Token = form.PolochonToken
|
||||
|
||||
err = user.SetConfig("polochon", polochonConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if form.Password != "" || form.PasswordVerify != "" {
|
||||
if form.Password != form.PasswordVerify {
|
||||
// TODO: manage form error
|
||||
}
|
||||
user.Hash, err = env.Auth.GenHash(form.Password)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
err = user.Update(env.Database)
|
||||
if err != nil {
|
||||
pretty.Println(err)
|
||||
return err
|
||||
}
|
||||
|
||||
err = env.Auth.RegenSecret(user, w, r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
web.SetData(r, "user", user)
|
||||
web.SetData(r, "polochon", polochonConfig)
|
||||
return env.Rends(w, r, "users/edit")
|
||||
}
|
||||
|
@ -11,9 +11,9 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
addUserQuery = `INSERT INTO users (name, hash, admin) VALUES ($1, $2, $3) RETURNING id;`
|
||||
addUserQuery = `INSERT INTO users (name, hash, admin, rawconfig) VALUES ($1, $2, $3, $4) RETURNING id;`
|
||||
getUserQuery = `SELECT * FROM users WHERE name=$1;`
|
||||
updateUserQuery = `UPDATE users SET name=:name, hash=:hash, admin=:admin RETURNING *;`
|
||||
updateUserQuery = `UPDATE users SET name=:name, hash=:hash, admin=:admin, rawconfig=:rawconfig WHERE id=:id RETURNING *;`
|
||||
deleteUseQuery = `DELETE FROM users WHERE id=:id;`
|
||||
|
||||
addTokenQuery = `INSERT INTO tokens (value, user_id) VALUES ($1, $2) RETURNING id;`
|
||||
@ -97,7 +97,7 @@ func Get(q sqlx.Queryer, name string) (*User, error) {
|
||||
// Add user to database or raises an error
|
||||
func (u *User) Add(q sqlx.Queryer) error {
|
||||
var id string
|
||||
err := q.QueryRowx(addUserQuery, u.Name, u.Hash, u.Admin).Scan(&id)
|
||||
err := q.QueryRowx(addUserQuery, u.Name, u.Hash, u.Admin, u.RawConfig).Scan(&id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
20
web/env.go
20
web/env.go
@ -34,20 +34,28 @@ type Env struct {
|
||||
|
||||
// NewEnv returns a new *Env
|
||||
func NewEnv(db *sqlx.DB, auth *auth.Authorizer, log *logrus.Entry, templatesDir string) *Env {
|
||||
return &Env{
|
||||
e := &Env{
|
||||
Database: db,
|
||||
Log: log,
|
||||
Router: mux.NewRouter(),
|
||||
Render: render.New(render.Options{
|
||||
Auth: auth,
|
||||
Mode: ProductionMode,
|
||||
}
|
||||
|
||||
tmplFuncs = append(tmplFuncs, map[string]interface{}{
|
||||
"URL": func(name string, pairs ...string) (string, error) {
|
||||
return e.GetURL(name, pairs...)
|
||||
},
|
||||
})
|
||||
|
||||
e.Render = render.New(render.Options{
|
||||
Directory: templatesDir,
|
||||
Layout: "layout",
|
||||
Funcs: tmplFuncs,
|
||||
DisableHTTPErrorRendering: true,
|
||||
RequirePartials: true,
|
||||
}),
|
||||
Auth: auth,
|
||||
Mode: ProductionMode,
|
||||
}
|
||||
})
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *Env) SetLoginRoute(name string) error {
|
||||
|
Loading…
x
Reference in New Issue
Block a user