diff --git a/auth/auth.go b/auth/auth.go index ab268d57..d6409c72 100644 --- a/auth/auth.go +++ b/auth/auth.go @@ -33,7 +33,7 @@ func Login(r *http.Request) (bool, error) { username, password := r.FormValue("username"), r.FormValue("password") session, _ := Store.Get(r, "gophish") u, err := models.GetUserByUsername(username) - if err != models.ErrUsernameTaken { + if err != nil && err != models.ErrUsernameTaken { return false, err } //If we've made it here, we should have a valid user stored in u @@ -61,7 +61,7 @@ func Register(r *http.Request) (bool, error) { h, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) u.Username = username u.Hash = string(h) - u.APIKey = GenerateSecureKey() + u.ApiKey = GenerateSecureKey() if err != nil { return false, err } diff --git a/controllers/api.go b/controllers/api.go index 17a880d0..e33ba787 100644 --- a/controllers/api.go +++ b/controllers/api.go @@ -39,7 +39,7 @@ func API_Reset(w http.ResponseWriter, r *http.Request) { switch { case r.Method == "POST": u := ctx.Get(r, "user").(models.User) - u.APIKey = auth.GenerateSecureKey() + u.ApiKey = auth.GenerateSecureKey() err := models.PutUser(&u) if err != nil { Flash(w, r, "danger", "Error resetting API Key") diff --git a/middleware/middleware.go b/middleware/middleware.go index 0d69d905..797bc3bf 100644 --- a/middleware/middleware.go +++ b/middleware/middleware.go @@ -52,12 +52,13 @@ func RequireAPIKey(handler http.Handler) http.HandlerFunc { if ak == "" { JSONError(w, 400, "API Key not set") } else { - id, err := models.Conn.SelectInt("SELECT id FROM users WHERE api_key=?", ak) - if id == 0 || err != nil { + u, err := models.GetUserByAPIKey(ak) + /* id, err := models.Conn.SelectInt("SELECT id FROM users WHERE api_key=?", ak) + */if err != nil { JSONError(w, 400, "Invalid API Key") return } - ctx.Set(r, "user_id", id) + ctx.Set(r, "user_id", u.Id) ctx.Set(r, "api_key", ak) handler.ServeHTTP(w, r) } diff --git a/models/campaign.go b/models/campaign.go index 9db54ee0..7c2e064b 100644 --- a/models/campaign.go +++ b/models/campaign.go @@ -9,39 +9,54 @@ import ( //Campaign is a struct representing a created campaign type Campaign struct { Id int64 `json:"id"` - Name string `json:"name"` - CreatedDate time.Time `json:"created_date" db:"created_date"` - CompletedDate time.Time `json:"completed_date" db:"completed_date"` + UserId int64 `json:"-"` + Name string `json:"name" sql:"not null"` + CreatedDate time.Time `json:"created_date"` + CompletedDate time.Time `json:"completed_date"` Template string `json:"template"` //This may change Status string `json:"status"` - Results []Result `json:"results,omitempty" db:"-"` - Groups []Group `json:"groups,omitempty" db:"-"` + Results []Result `json:"results,omitempty"` + Groups []Group `json:"groups,omitempty"` } type Result struct { - Target - Status string `json:"status"` + Id int64 `json:"-"` + CampaignId int64 `json:"-"` + Email string `json:"email"` + Status string `json:"status" sql:"not null"` } // GetCampaigns returns the campaigns owned by the given user. func GetCampaigns(uid int64) ([]Campaign, error) { cs := []Campaign{} - _, err := Conn.Select(&cs, "SELECT c.id, name, created_date, completed_date, status, template FROM campaigns c, user_campaigns uc, users u WHERE uc.uid=u.id AND uc.cid=c.id AND u.id=?", uid) - for i, _ := range cs { - _, err = Conn.Select(&cs[i].Results, "SELECT r.email, r.status FROM campaign_results r WHERE r.cid=?", cs[i].Id) + err := db.Debug().Model(&User{Id: uid}).Related(&cs).Error + if err != nil { + fmt.Println(err) } + /* _, err = Conn.Select(&cs, "SELECT c.id, name, created_date, completed_date, status, template FROM campaigns c, user_campaigns uc, users u WHERE uc.uid=u.id AND uc.cid=c.id AND u.id=?", uid) + */for i, _ := range cs { + err := db.Debug().Model(&cs[i]).Related(&cs[i].Results).Error + if err != nil { + fmt.Println(err) + } + /* _, err = Conn.Select(&cs[i].Results, "SELECT r.email, r.status FROM campaign_results r WHERE r.cid=?", cs[i].Id) + */ + } + fmt.Printf("%v", cs) return cs, err } // GetCampaign returns the campaign, if it exists, specified by the given id and user_id. func GetCampaign(id int64, uid int64) (Campaign, error) { c := Campaign{} - err := Conn.SelectOne(&c, "SELECT c.id, name, created_date, completed_date, status, template FROM campaigns c, user_campaigns uc, users u WHERE uc.uid=u.id AND uc.cid=c.id AND c.id=? AND u.id=?", id, uid) - if err != nil { + err := db.Debug().Where("id = ?", id).Where("user_id = ?", uid).Find(&c).Error + /* err := Conn.SelectOne(&c, "SELECT c.id, name, created_date, completed_date, status, template FROM campaigns c, user_campaigns uc, users u WHERE uc.uid=u.id AND uc.cid=c.id AND c.id=? AND u.id=?", id, uid) + */if err != nil { return c, err } - _, err = Conn.Select(&c.Results, "SELECT r.email, r.status FROM campaign_results r WHERE r.cid=?", c.Id) - return c, err + err = db.Debug().Model(&c).Related(&c.Results).Error + /* _, err = Conn.Select(&c.Results, "SELECT r.email, r.status FROM campaign_results r WHERE r.cid=?", c.Id) + */return c, err } // PostCampaign inserts a campaign and all associated records into the database. @@ -58,7 +73,8 @@ func PostCampaign(c *Campaign, uid int64) error { } } // Insert into the DB - err = Conn.Insert(c) + /*err = Conn.Insert(c)*/ + err = db.Debug().Save(&c).Error if err != nil { Logger.Println(err) return err @@ -67,35 +83,40 @@ func PostCampaign(c *Campaign, uid int64) error { for _, g := range c.Groups { // Insert a result for each target in the group for _, t := range g.Targets { - r := Result{Target: t, Status: "Unknown"} + r := Result{Email: t.Email, Status: "Unknown", CampaignId: c.Id} c.Results = append(c.Results, r) fmt.Printf("%v", c.Results) - _, err = Conn.Exec("INSERT INTO campaign_results VALUES (?,?,?)", c.Id, r.Email, r.Status) + err := db.Debug().Save(&r).Error + /*_, err = Conn.Exec("INSERT INTO campaign_results VALUES (?,?,?)", c.Id, r.Email, r.Status)*/ if err != nil { Logger.Printf("Error adding result record for target %s\n", t.Email) Logger.Println(err) } } } - _, err = Conn.Exec("INSERT OR IGNORE INTO user_campaigns VALUES (?,?)", uid, c.Id) + /*_, err = Conn.Exec("INSERT OR IGNORE INTO user_campaigns VALUES (?,?)", uid, c.Id) if err != nil { Logger.Printf("Error adding many-many mapping for campaign %s\n", c.Name) - } + }*/ return nil } func DeleteCampaign(id int64) error { // Delete all the campaign_results entries for this group - _, err := Conn.Exec("DELETE FROM campaign_results WHERE cid=?", id) + err := db.Debug().Delete(&Result{CampaignId: id}).Error + /*_, err := Conn.Exec("DELETE FROM campaign_results WHERE cid=?", id)*/ if err != nil { + Logger.Println(err) return err } // Delete the reference to the campaign in the user_campaigns table - _, err = Conn.Exec("DELETE FROM user_campaigns WHERE cid=?", id) + err = db.Debug().Delete(&Campaign{Id: id}).Error + /*_, err = Conn.Exec("DELETE FROM user_campaigns WHERE cid=?", id)*/ if err != nil { + Logger.Panicln(err) return err } // Delete the campaign itself - _, err = Conn.Exec("DELETE FROM campaigns WHERE id=?", id) + /*_, err = Conn.Exec("DELETE FROM campaigns WHERE id=?", id)*/ return err } diff --git a/models/group.go b/models/group.go index 1305dda4..bb2295bc 100644 --- a/models/group.go +++ b/models/group.go @@ -8,8 +8,18 @@ import ( type Group struct { Id int64 `json:"id"` Name string `json:"name"` - ModifiedDate time.Time `json:"modified_date" db:"modified_date"` - Targets []Target `json:"targets" db:"-"` + ModifiedDate time.Time `json:"modified_date"` + Targets []Target `json:"targets" sql:"-"` +} + +type UserGroup struct { + UserId int64 `json:"-"` + GroupId int64 `json:"-"` +} + +type GroupTarget struct { + GroupId int64 `json:"-"` + TargetId int64 `json:"-"` } type Target struct { @@ -20,13 +30,14 @@ type Target struct { // GetGroups returns the groups owned by the given user. func GetGroups(uid int64) ([]Group, error) { gs := []Group{} - _, err := Conn.Select(&gs, "SELECT g.id, g.name, g.modified_date FROM groups g, user_groups ug, users u WHERE ug.uid=u.id AND ug.gid=g.id AND u.id=?", uid) + err := db.Debug().Table("groups g").Select("g.id, g.name, g.modified_date").Joins("left join user_groups ug ON g.id = ug.group_id").Where("ug.user_id=?", uid).Scan(&gs).Error + /*_, err := Conn.Select(&gs, "SELECT g.id, g.name, g.modified_date FROM groups g, user_groups ug, users u WHERE ug.uid=u.id AND ug.gid=g.id AND u.id=?", uid)*/ if err != nil { Logger.Println(err) return gs, err } for i, _ := range gs { - _, err := Conn.Select(&gs[i].Targets, "SELECT t.id, t.email FROM targets t, group_targets gt WHERE gt.gid=? AND gt.tid=t.id", gs[i].Id) + gs[i].Targets, err = GetTargets(gs[i].Id) if err != nil { Logger.Println(err) } @@ -37,12 +48,14 @@ func GetGroups(uid int64) ([]Group, error) { // GetGroup returns the group, if it exists, specified by the given id and user_id. func GetGroup(id int64, uid int64) (Group, error) { g := Group{} - err := Conn.SelectOne(&g, "SELECT g.id, g.name, g.modified_date FROM groups g, user_groups ug, users u WHERE ug.uid=u.id AND ug.gid=g.id AND g.id=? AND u.id=?", id, uid) + err := db.Debug().Table("groups g").Select("g.id, g.name, g.modified_date").Joins("left join user_groups ug ON g.id = ug.group_id").Where("ug.user_id=? and g.id=?", uid, id).Scan(&g).Error + /*err := Conn.SelectOne(&g, "SELECT g.id, g.name, g.modified_date FROM groups g, user_groups ug, users u WHERE ug.uid=u.id AND ug.gid=g.id AND g.id=? AND u.id=?", id, uid)*/ if err != nil { Logger.Println(err) return g, err } - _, err = Conn.Select(&g.Targets, "SELECT t.id, t.email FROM targets t, group_targets gt WHERE gt.gid=? AND gt.tid=t.id", g.Id) + g.Targets, err = GetTargets(g.Id) + /*_, err = Conn.Select(&g.Targets, "SELECT t.id, t.email FROM targets t, group_targets gt WHERE gt.gid=? AND gt.tid=t.id", g.Id)*/ if err != nil { Logger.Println(err) } @@ -52,12 +65,14 @@ func GetGroup(id int64, uid int64) (Group, error) { // GetGroupByName returns the group, if it exists, specified by the given name and user_id. func GetGroupByName(n string, uid int64) (Group, error) { g := Group{} - err := Conn.SelectOne(&g, "SELECT g.id, g.name, g.modified_date FROM groups g, user_groups ug, users u WHERE ug.uid=u.id AND ug.gid=g.id AND g.name=? AND u.id=?", n, uid) + err := db.Debug().Table("groups g").Select("g.id, g.name, g.modified_date").Joins("left join user_groups ug ON g.id = ug.group_id").Where("ug.user_id=? and g.name=?", uid, n).Scan(&g).Error + /*err := Conn.SelectOne(&g, "SELECT g.id, g.name, g.modified_date FROM groups g, user_groups ug, users u WHERE ug.uid=u.id AND ug.gid=g.id AND g.name=? AND u.id=?", n, uid)*/ if err != nil { Logger.Println(err) return g, err } - _, err = Conn.Select(&g.Targets, "SELECT t.id, t.email FROM targets t, group_targets gt WHERE gt.gid=? AND gt.tid=t.id", g.Id) + g.Targets, err = GetTargets(g.Id) + /*_, err = Conn.Select(&g.Targets, "SELECT t.id, t.email FROM targets t, group_targets gt WHERE gt.gid=? AND gt.tid=t.id", g.Id)*/ if err != nil { Logger.Println(err) } @@ -67,16 +82,22 @@ func GetGroupByName(n string, uid int64) (Group, error) { // PostGroup creates a new group in the database. func PostGroup(g *Group, uid int64) error { // Insert into the DB - err = Conn.Insert(g) + /*err = Conn.Insert(g)*/ + err = db.Save(&g).Error if err != nil { Logger.Println(err) return err } // Now, let's add the user->user_groups->group mapping - _, err = Conn.Exec("INSERT OR IGNORE INTO user_groups VALUES (?,?)", uid, g.Id) + err = db.Save(&UserGroup{GroupId: g.Id, UserId: uid}).Error + if err != nil { + Logger.Println(err) + return err + } + /*_, err = Conn.Exec("INSERT OR IGNORE INTO user_groups VALUES (?,?)", uid, g.Id) if err != nil { Logger.Printf("Error adding many-many mapping for group %s\n", g.Name) - } + }*/ for _, t := range g.Targets { insertTargetIntoGroup(t, g.Id) } @@ -90,7 +111,8 @@ func PutGroup(g *Group, uid int64) error { // since they are needed by the Results table // Get all the targets currently in the database for the group ts := []Target{} - _, err = Conn.Select(&ts, "SELECT t.id, t.email FROM targets t, group_targets gt WHERE gt.gid=? AND gt.tid=t.id", g.Id) + ts, err = GetTargets(g.Id) + /*_, err = Conn.Select(&ts, "SELECT t.id, t.email FROM targets t, group_targets gt WHERE gt.gid=? AND gt.tid=t.id", g.Id)*/ if err != nil { Logger.Printf("Error getting targets from group ID: %d", g.Id) return err @@ -133,7 +155,8 @@ func PutGroup(g *Group, uid int64) error { } // Update the group g.ModifiedDate = time.Now() - _, err = Conn.Update(g) + err = db.Debug().Update(&g).Error + /*_, err = Conn.Update(g)*/ if err != nil { Logger.Println(err) return err @@ -178,16 +201,35 @@ func insertTargetIntoGroup(t Target, gid int64) error { // DeleteGroup deletes a given group by group ID and user ID func DeleteGroup(id int64) error { // Delete all the group_targets entries for this group - _, err := Conn.Exec("DELETE FROM group_targets WHERE gid=?", id) + err := db.Debug().Where("group_id=?", id).Delete(&GroupTarget{}).Error + /*_, err := Conn.Exec("DELETE FROM group_targets WHERE gid=?", id)*/ if err != nil { + Logger.Println(err) return err } // Delete the reference to the group in the user_group table - _, err = Conn.Exec("DELETE FROM user_groups WHERE gid=?", id) + err = db.Debug().Where("group_id=?", id).Delete(&UserGroup{}).Error + /*_, err = Conn.Exec("DELETE FROM user_groups WHERE gid=?", id)*/ if err != nil { + Logger.Println(err) return err } // Delete the group itself - _, err = Conn.Exec("DELETE FROM groups WHERE id=?", id) + err = db.Debug().Delete(&Group{Id: id}).Error + /*_, err = Conn.Exec("DELETE FROM groups WHERE id=?", id)*/ + if err != nil { + Logger.Println(err) + return err + } return err } + +func GetTargets(gid int64) ([]Target, error) { + ts := []Target{} + err := db.Debug().Table("targets t").Select("t.id, t.email").Joins("left join group_targets gt ON t.id = gt.target_id").Where("gt.group_id=?", gid).Scan(&ts).Error + /*_, err := Conn.Select(&gs[i].Targets, "SELECT t.id, t.email FROM targets t, group_targets gt WHERE gt.gid=? AND gt.tid=t.id", gs[i].Id)*/ + if err != nil { + return nil, err + } + return ts, nil +} diff --git a/models/models.go b/models/models.go index daf8343d..ce34aea9 100644 --- a/models/models.go +++ b/models/models.go @@ -3,24 +3,41 @@ package models import ( "database/sql" "errors" + "fmt" "log" "os" + "time" "github.com/coopernurse/gorp" + "github.com/jinzhu/gorm" "github.com/jordan-wright/gophish/config" _ "github.com/mattn/go-sqlite3" ) var Conn *gorp.DbMap +var db gorm.DB var DB *sql.DB var err error -var ErrUsernameTaken = errors.New("Username already taken") -var Logger = log.New(os.Stdout, "", log.Ldate|log.Ltime|log.Lshortfile) +var ErrUsernameTaken = errors.New("username already taken") +var Logger = log.New(os.Stdout, " ", log.Ldate|log.Ltime|log.Lshortfile) // Setup initializes the Conn object // It also populates the Gophish Config object func Setup() error { DB, err := sql.Open("sqlite3", config.Conf.DBPath) + if err != nil { + fmt.Printf("%v", err) + } + db, err = gorm.Open("sqlite3", "gophish_gorm.db") + db.SetLogger(Logger) + db.CreateTable(User{}) + db.CreateTable(Target{}) + db.CreateTable(Result{}) + db.CreateTable(Group{}) + db.CreateTable(GroupTarget{}) + db.CreateTable(UserGroup{}) + db.CreateTable(Template{}) + db.CreateTable(Campaign{}) Conn = &gorp.DbMap{Db: DB, Dialect: gorp.SqliteDialect{}} //If the file already exists, delete it and recreate it _, err = os.Stat(config.Conf.DBPath) @@ -57,9 +74,63 @@ func Setup() error { init_user := User{ Username: "admin", Hash: "$2a$10$IYkPp0.QsM81lYYPrQx6W.U6oQGw7wMpozrKhKAHUBVL4mkm/EvAS", //gophish - APIKey: "12345678901234567890123456789012", + ApiKey: "12345678901234567890123456789012", } - Conn.Insert(&init_user) + err = db.Save(&init_user).Error + if err != nil { + Logger.Println(err) + } + init_campaign := Campaign{ + UserId: 1, + Name: "First Campaign", + CreatedDate: time.Now(), //gophish + CompletedDate: time.Now(), + Template: "", + Status: "In Progress", + Results: []Result{}, + Groups: []Group{}, + } + err = db.Debug().Save(&init_campaign).Error + if err != nil { + Logger.Println(err) + } + init_result := Result{ + CampaignId: 1, + Email: "test@example.com", + Status: "Unsuccessful", + } + err = db.Debug().Save(&init_result).Error + if err != nil { + Logger.Println(err) + } + init_group := Group{ + Name: "New Group", + ModifiedDate: time.Now(), + } + err = db.Debug().Save(&init_group).Error + if err != nil { + Logger.Println(err) + } + init_ug := UserGroup{ + UserId: 1, + GroupId: 1, + } + err = db.Debug().Save(&init_ug).Error + if err != nil { + Logger.Println(err) + } + init_target := Target{ + Email: "test@example.com", + } + err = db.Debug().Save(&init_target).Error + if err != nil { + Logger.Println(err) + } + init_gt := GroupTarget{ + GroupId: 1, + TargetId: 1, + } + err = db.Debug().Save(&init_gt).Error if err != nil { Logger.Println(err) } diff --git a/models/template.go b/models/template.go index 39f01dfd..eb97476f 100644 --- a/models/template.go +++ b/models/template.go @@ -4,10 +4,10 @@ import "time" type Template struct { Id int64 `json:"id"` - Name string `json:"name" db:"name"` - Text string `json:"text" db:"text"` - Html string `json:"html" db:"html"` - ModifiedDate time.Time `json:"modified_date" db:"modified_date"` + Name string `json:"name"` + Text string `json:"text"` + Html string `json:"html"` + ModifiedDate time.Time `json:"modified_date"` } // GetTemplates returns the templates owned by the given user. diff --git a/models/user.go b/models/user.go index 2f329905..c3e52ed2 100644 --- a/models/user.go +++ b/models/user.go @@ -5,16 +5,17 @@ import "database/sql" // User represents the user model for gophish. type User struct { Id int64 `json:"id"` - Username string `json:"username"` + Username string `json:"username"` /* sql:"not null;unique"`*/ Hash string `json:"-"` - APIKey string `json:"api_key" db:"api_key"` + ApiKey string `json:"api_key" db:"api_key"` /* sql:"not null;unique"`*/ } // GetUser returns the user that the given id corresponds to. If no user is found, an // error is thrown. func GetUser(id int64) (User, error) { u := User{} - err := Conn.SelectOne(&u, "SELECT * FROM Users WHERE id=?", id) + /* err := Conn.SelectOne(&u, "SELECT * FROM Users WHERE id=?", id)*/ + err := db.Where("id=?", id).First(&u).Error if err != nil { return u, err } @@ -23,9 +24,10 @@ func GetUser(id int64) (User, error) { // GetUserByAPIKey returns the user that the given API Key corresponds to. If no user is found, an // error is thrown. -func GetUserByAPIKey(key []byte) (User, error) { +func GetUserByAPIKey(key string) (User, error) { u := User{} - err := Conn.SelectOne(&u, "SELECT id, username, api_key FROM Users WHERE apikey=?", key) + /* err := Conn.SelectOne(&u, "SELECT id, username, api_key FROM Users WHERE apikey=?", key)*/ + err := db.Debug().Where("api_key = ?", key).First(&u).Error if err != nil { return u, err } @@ -36,7 +38,8 @@ func GetUserByAPIKey(key []byte) (User, error) { // error is thrown. func GetUserByUsername(username string) (User, error) { u := User{} - err := Conn.SelectOne(&u, "SELECT * FROM Users WHERE username=?", username) + /* err := Conn.SelectOne(&u, "SELECT * FROM Users WHERE username=?", username)*/ + err := db.Where("username = ?", username).First(&u).Error if err != sql.ErrNoRows { return u, ErrUsernameTaken } else if err != nil { @@ -47,6 +50,7 @@ func GetUserByUsername(username string) (User, error) { // PutUser updates the given user func PutUser(u *User) error { - _, err := Conn.Update(u) + err := db.Debug().Update(&u).Error + /*_, err := Conn.Update(u)*/ return err } diff --git a/templates/base.html b/templates/base.html index fa1404e6..9f7fc38a 100644 --- a/templates/base.html +++ b/templates/base.html @@ -20,7 +20,7 @@ {{%if .User%}} - + {{%end%}}