Cleaned up some errors

Implemented using db.* helpers (ie GetUser)
Implemented ChangePassword (not reachable from UI currently)
Fixed angular issue in settings.html template
pull/24/head
Jordan 2014-02-06 10:49:53 -06:00
parent af7a8f4c4e
commit 40cd2ae837
7 changed files with 77 additions and 70 deletions

View File

@ -1,9 +1,7 @@
package auth
import (
"database/sql"
"encoding/gob"
"errors"
"fmt"
"io"
"net/http"
@ -27,24 +25,20 @@ var Store = sessions.NewCookieStore(
[]byte(securecookie.GenerateRandomKey(64)), //Signing key
[]byte(securecookie.GenerateRandomKey(32)))
var ErrUsernameTaken = errors.New("Username already taken")
// Login attempts to login the user given a request.
func Login(r *http.Request) (bool, error) {
username, password := r.FormValue("username"), r.FormValue("password")
session, _ := Store.Get(r, "gophish")
u := models.User{}
err := db.Conn.SelectOne(&u, "SELECT * FROM Users WHERE username=?", username)
if err == sql.ErrNoRows {
u, err := db.GetUserByUsername(username)
if err != db.ErrUsernameTaken {
//Return false, but don't return an error
return false, nil
} else if err != nil {
return false, err
}
//If we've made it here, we should have a valid user stored in u
//Let's check the password
err = bcrypt.CompareHashAndPassword([]byte(u.Hash), []byte(password))
if err != nil {
fmt.Println("Error in comparing hash and password")
ctx.Set(r, "user", nil)
//Return false, but don't return an error
return false, nil
@ -57,10 +51,9 @@ func Login(r *http.Request) (bool, error) {
// Register attempts to register the user given a request.
func Register(r *http.Request) (bool, error) {
username, password := r.FormValue("username"), r.FormValue("password")
u := models.User{}
err := db.Conn.SelectOne(&u, "SELECT * FROM Users WHERE username=?", username)
if err != sql.ErrNoRows {
return false, ErrUsernameTaken
u, err := db.GetUserByUsername(username)
if err != nil {
return false, err
}
//If we've made it here, we should have a valid username given
//Let's create the password hash
@ -78,31 +71,28 @@ func Register(r *http.Request) (bool, error) {
return true, nil
}
// GetUserById returns the user that the given id corresponds to. If no user is found, an
// error is thrown.
func GetUserById(id int64) (models.User, error) {
u := models.User{}
err := db.Conn.SelectOne(&u, "SELECT id, username, api_key FROM Users WHERE id=?", id)
if err != nil {
return u, err
}
return u, nil
}
// GetUserByAPIKey returns the user that the given API Key corresponds to. If no user is found, an
// error is thrown.
func GetUserByAPIKey(key []byte) (models.User, error) {
u := models.User{}
err := db.Conn.SelectOne(&u, "SELECT id, username, api_key FROM Users WHERE apikey=?", key)
if err != nil {
return u, err
}
return u, nil
}
func GenerateSecureKey() string {
// Inspired from gorilla/securecookie
k := make([]byte, 32)
io.ReadFull(rand.Reader, k)
return fmt.Sprintf("%x", k)
}
func ChangePassword(u *models.User, c string, n string) bool {
// Check the current password
err := bcrypt.CompareHashAndPassword([]byte(u.Hash), []byte(c))
if err != nil {
return false
} else {
// Generate the new hash
h, err := bcrypt.GenerateFromPassword([]byte(n), bcrypt.DefaultCost)
if err != nil {
return false
}
u.Hash = string(h)
if err = db.PutUser(u); err != nil {
return false
}
return true
}
}

View File

@ -10,7 +10,6 @@ import (
ctx "github.com/gorilla/context"
"github.com/gorilla/mux"
"github.com/gorilla/sessions"
"github.com/jordan-wright/gophish/auth"
"github.com/jordan-wright/gophish/db"
"github.com/jordan-wright/gophish/models"
@ -37,13 +36,12 @@ func API_Reset(w http.ResponseWriter, r *http.Request) {
case r.Method == "POST":
u := ctx.Get(r, "user").(models.User)
u.APIKey = auth.GenerateSecureKey()
db.Conn.Exec("UPDATE users SET api_key=? WHERE id=?", u.APIKey, u.Id)
session := ctx.Get(r, "session").(*sessions.Session)
session.AddFlash(models.Flash{
Type: "success",
Message: "API Key Successfully Reset",
})
session.Save(r, w)
err := db.PutUser(&u)
if err != nil {
Flash(w, r, "danger", "Error resetting API Key")
} else {
Flash(w, r, "success", "API Key Successfully Reset")
}
http.Redirect(w, r, "/settings", 302)
}
}
@ -53,8 +51,7 @@ func API_Reset(w http.ResponseWriter, r *http.Request) {
func API_Campaigns(w http.ResponseWriter, r *http.Request) {
switch {
case r.Method == "GET":
cs := []models.Campaign{}
_, err := db.Conn.Select(&cs, "SELECT c.id, name, created_date, completed_date, status, template FROM campaigns c, users u WHERE c.uid=u.id AND u.api_key=?", ctx.Get(r, "api_key"))
cs, err := db.GetCampaigns(ctx.Get(r, "api_key"))
if err != nil {
fmt.Println(err)
}
@ -96,14 +93,11 @@ func API_Campaigns(w http.ResponseWriter, r *http.Request) {
// valid, API_Campaigns_Id returns null.
func API_Campaigns_Id(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
id, err := strconv.ParseInt(vars["id"], 0, 64)
if checkError(err, w, "Invalid Int") {
return
}
id, _ := strconv.ParseInt(vars["id"], 0, 64)
switch {
case r.Method == "GET":
c := models.Campaign{}
err := db.Conn.SelectOne(&c, "SELECT campaigns.id, name, created_date, completed_date, status, template FROM campaigns, users WHERE campaigns.uid=users.id AND campaigns.id =? AND users.api_key=?", id, ctx.Get(r, "api_key"))
c, err := db.GetCampaign(id, ctx.Get(r, "api_key"))
if checkError(err, w, "No campaign found") {
return
}

View File

@ -173,8 +173,8 @@ func Login(w http.ResponseWriter, r *http.Request) {
case r.Method == "POST":
//Attempt to login
succ, err := auth.Login(r)
if checkError(err, w, "Error logging in") {
return
if err != nil {
fmt.Println(err)
}
//If we've logged in, save the session and redirect to the dashboard
if succ {

View File

@ -118,6 +118,13 @@ func GetCampaigns(key interface{}) ([]models.Campaign, error) {
return cs, err
}
func GetCampaign(id int64) {
func GetCampaign(id int64, key interface{}) (models.Campaign, error) {
c := models.Campaign{}
err := Conn.SelectOne(&c, "SELECT campaigns.id, name, created_date, completed_date, status, template FROM campaigns, users WHERE campaigns.uid=users.id AND campaigns.id =? AND users.api_key=?", id, key)
return c, err
}
func PutCampaign(c *models.Campaign) error {
_, err := Conn.Update(c)
return err
}

View File

@ -82,3 +82,7 @@
p {
font-size:1.2em;
}
.form-label {
padding-top:7px;
}

View File

@ -23,22 +23,9 @@
{{%template "flashes" .Flashes%}}
<h1 style="margin:0px 0px 15px 0px;">User Settings</h1>
<div class="row">
<div class="col-md-2">
<p><b>Username:</b>
</p>
</div>
<label for="api_key" class="col-sm-2 control-label form-label">API Key:</label>
<div class="col-md-6">
<input type="text" value="{{%.User.Username%}}" class="form-control" />
</div>
</div>
<br/>
<div class="row">
<div class="col-md-2">
<p><b>API Key:</b>
</p>
</div>
<div class="col-md-6">
<input type="text" onclick="this.select();" value="{{%.User.APIKey%}}" class="form-control" readonly/>
<input type="text" id="api_key" onclick="this.select();" value="{{%.User.APIKey%}}" class="form-control" readonly/>
</div>
<form action="/api/reset" method="POST">
<button class="btn btn-primary"><i class="fa fa-refresh" type="submit"></i> Reset</button>
@ -46,6 +33,29 @@
</form>
</div>
<br />
<form action="/settings" method="POST">
<div class="row">
<label for="username" class="col-sm-2 control-label form-label">Username:</label>
<div class="col-md-6">
<input type="text" id="username" value="{{%.User.Username%}}" class="form-control" />
</div>
</div>
<br />
<div class="row">
<label for="current_password" class="col-sm-2 control-label form-label">Old Password:</label>
<div class="col-md-6">
<input type="password" id="current_password" class="form-control" />
</div>
</div>
<br />
<div class="row">
<label for="new_password" class="col-sm-2 control-label form-label">New Password:</label>
<div class="col-md-6">
<input type="password" id="new_password" class="form-control" />
</div>
</div>
</form>
<br/>
<button class="btn btn-primary">Save</button>
</div>
</div>

View File

@ -36,7 +36,9 @@
<tbody>
<tr ng-repeat="group in groups">
<td>{{group.name}}</td>
<td>{{group.targets}}</td>
<td><span ng-repeat="target in group.targets">
{{target.email}}{{$last ? '' : ', '}}
</span></td>
<td>{{group.modified_date | date:'medium'}}</td>
</tr>
</tbody>