2014-01-09 06:42:05 +00:00
package controllers
import (
2014-01-13 02:00:20 +00:00
"encoding/json"
2014-01-09 06:42:05 +00:00
"fmt"
"net/http"
2014-02-05 03:08:09 +00:00
"net/mail"
2014-02-01 02:49:22 +00:00
"strconv"
2014-01-31 22:25:02 +00:00
"time"
2014-01-09 06:42:05 +00:00
2014-01-13 02:00:20 +00:00
ctx "github.com/gorilla/context"
2014-01-09 06:42:05 +00:00
"github.com/gorilla/mux"
2014-02-05 00:39:01 +00:00
"github.com/jordan-wright/gophish/auth"
2014-01-31 04:46:25 +00:00
"github.com/jordan-wright/gophish/db"
"github.com/jordan-wright/gophish/models"
2014-01-09 06:42:05 +00:00
)
2014-01-31 22:25:02 +00:00
const (
IN_PROGRESS string = "In progress"
WAITING string = "Waiting"
COMPLETE string = "Completed"
ERROR string = "Error"
)
2014-02-01 03:49:35 +00:00
// API (/api) provides access to api documentation
2014-01-09 06:42:05 +00:00
func API ( w http . ResponseWriter , r * http . Request ) {
2014-02-01 03:49:35 +00:00
switch {
case r . Method == "GET" :
getTemplate ( w , "api_doc" ) . ExecuteTemplate ( w , "base" , nil )
2014-01-13 02:00:20 +00:00
}
2014-01-09 06:42:05 +00:00
}
2014-02-02 20:47:06 +00:00
// API (/api/reset) resets a user's API key
func API_Reset ( w http . ResponseWriter , r * http . Request ) {
switch {
2014-02-03 23:21:56 +00:00
case r . Method == "POST" :
2014-02-02 20:47:06 +00:00
u := ctx . Get ( r , "user" ) . ( models . User )
2014-02-05 00:39:01 +00:00
u . APIKey = auth . GenerateSecureKey ( )
2014-02-06 16:49:53 +00:00
err := db . PutUser ( & u )
if err != nil {
Flash ( w , r , "danger" , "Error resetting API Key" )
} else {
Flash ( w , r , "success" , "API Key Successfully Reset" )
}
2014-02-02 20:47:06 +00:00
http . Redirect ( w , r , "/settings" , 302 )
}
}
2014-02-01 03:49:35 +00:00
// API_Campaigns returns a list of campaigns if requested via GET.
// If requested via POST, API_Campaigns creates a new campaign and returns a reference to it.
2014-01-09 06:42:05 +00:00
func API_Campaigns ( w http . ResponseWriter , r * http . Request ) {
switch {
case r . Method == "GET" :
2014-02-06 16:49:53 +00:00
cs , err := db . GetCampaigns ( ctx . Get ( r , "api_key" ) )
2014-01-31 04:46:25 +00:00
if err != nil {
fmt . Println ( err )
}
2014-02-02 20:47:06 +00:00
/ * for c := range cs {
_ , err := db . Conn . Select ( & cs . Results , "SELECT r.id " )
} * /
2014-01-31 22:25:02 +00:00
cj , err := json . MarshalIndent ( cs , "" , " " )
if checkError ( err , w , "Error looking up campaigns" ) {
return
2014-01-31 04:46:25 +00:00
}
2014-01-31 22:25:02 +00:00
writeJSON ( w , cj )
2014-02-02 20:47:06 +00:00
//POST: Create a new campaign and return it as JSON
2014-01-09 06:42:05 +00:00
case r . Method == "POST" :
2014-01-31 22:25:02 +00:00
c := models . Campaign { }
// Put the request into a campaign
err := json . NewDecoder ( r . Body ) . Decode ( & c )
2014-02-05 00:39:01 +00:00
if checkError ( err , w , "Invalid Request" ) {
return
}
2014-01-31 22:25:02 +00:00
// Fill in the details
c . CreatedDate = time . Now ( )
c . CompletedDate = time . Time { }
c . Status = IN_PROGRESS
2014-02-05 00:39:01 +00:00
c . Uid = ctx . Get ( r , "user_id" ) . ( int64 )
2014-01-31 22:25:02 +00:00
// Insert into the DB
err = db . Conn . Insert ( & c )
if checkError ( err , w , "Cannot insert campaign into database" ) {
return
}
cj , err := json . MarshalIndent ( c , "" , " " )
if checkError ( err , w , "Error creating JSON response" ) {
return
}
writeJSON ( w , cj )
2014-01-09 06:42:05 +00:00
}
}
2014-02-01 03:49:35 +00:00
// API_Campaigns_Id returns details about the requested campaign. If the campaign is not
// valid, API_Campaigns_Id returns null.
2014-01-09 06:42:05 +00:00
func API_Campaigns_Id ( w http . ResponseWriter , r * http . Request ) {
vars := mux . Vars ( r )
2014-02-06 16:49:53 +00:00
id , _ := strconv . ParseInt ( vars [ "id" ] , 0 , 64 )
2014-02-01 02:49:22 +00:00
switch {
case r . Method == "GET" :
c := models . Campaign { }
2014-02-06 16:49:53 +00:00
c , err := db . GetCampaign ( id , ctx . Get ( r , "api_key" ) )
2014-02-01 02:49:22 +00:00
if checkError ( err , w , "No campaign found" ) {
return
}
cj , err := json . MarshalIndent ( c , "" , " " )
if checkError ( err , w , "Error creating JSON response" ) {
return
}
writeJSON ( w , cj )
case r . Method == "DELETE" :
//c := models.Campaign{}
}
2014-01-09 06:42:05 +00:00
}
2014-02-04 05:41:31 +00:00
func API_Campaigns_Id_Launch ( w http . ResponseWriter , r * http . Request ) {
http . Redirect ( w , r , "/" , 302 )
}
2014-02-02 22:37:36 +00:00
// API_Groups returns details about the requested group. If the campaign is not
// valid, API_Groups returns null.
2014-02-05 03:08:09 +00:00
// Example:
/ *
POST / api / groups
{ "name" : "Test Group" ,
2014-02-05 03:53:11 +00:00
"targets" : [
{
"email" : "test@example.com"
} ,
{ "email" : test2 @ example . com "
} ]
2014-02-05 03:08:09 +00:00
}
RESULT { "name" : "Test Group" ,
"targets" : [ "test@example.com" , "test2@example.com" ]
"id" : 1
}
* /
2014-02-02 22:37:36 +00:00
func API_Groups ( w http . ResponseWriter , r * http . Request ) {
2014-02-05 00:39:01 +00:00
switch {
case r . Method == "GET" :
gs := [ ] models . Group { }
2014-02-05 03:53:11 +00:00
_ , err := db . Conn . Select ( & gs , "SELECT g.id, g.name, g.modified_date FROM groups g, users u, user_groups ug WHERE ug.uid=u.id AND ug.gid=g.id AND u.api_key=?" , ctx . Get ( r , "api_key" ) )
2014-02-05 00:39:01 +00:00
if err != nil {
fmt . Println ( err )
}
2014-02-05 03:53:11 +00:00
for i , _ := range gs {
2014-02-06 17:14:51 +00:00
_ , err := db . 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 )
2014-02-05 00:39:01 +00:00
if checkError ( err , w , "Error looking up groups" ) {
return
}
}
gj , err := json . MarshalIndent ( gs , "" , " " )
if checkError ( err , w , "Error looking up groups" ) {
return
}
writeJSON ( w , gj )
//POST: Create a new group and return it as JSON
case r . Method == "POST" :
g := models . Group { }
// Put the request into a group
err := json . NewDecoder ( r . Body ) . Decode ( & g )
if checkError ( err , w , "Invalid Request" ) {
return
}
// Check to make sure targets were specified
if len ( g . Targets ) == 0 {
http . Error ( w , "Error: No targets specified" , http . StatusInternalServerError )
return
}
g . ModifiedDate = time . Now ( )
// Insert into the DB
err = db . Conn . Insert ( & g )
if checkError ( err , w , "Cannot insert group into database" ) {
return
}
2014-02-05 03:08:09 +00:00
// Let's start a transaction to handle the bulk inserting
trans , err := db . Conn . Begin ( )
if checkError ( err , w , "Error starting transaction to insert data" ) {
return
}
// Now, let's add the user->user_groups->group mapping
2014-02-05 03:53:11 +00:00
_ , err = db . Conn . Exec ( "INSERT OR IGNORE INTO user_groups VALUES (?,?)" , ctx . Get ( r , "user_id" ) . ( int64 ) , g . Id )
if err != nil {
fmt . Printf ( "Error adding many-many mapping for group %s\n" , g . Name )
}
2014-02-05 03:08:09 +00:00
// TODO
for _ , t := range g . Targets {
if _ , err = mail . ParseAddress ( t . Email ) ; err != nil {
fmt . Printf ( "Found invalid email %s\n" , t . Email )
continue
}
2014-02-06 17:14:51 +00:00
_ , err := db . Conn . Exec ( "INSERT OR IGNORE INTO targets VALUES (null, ?)" , t . Email )
2014-02-05 03:08:09 +00:00
if err != nil {
fmt . Printf ( "Error adding email: %s\n" , t . Email )
}
2014-02-06 17:14:51 +00:00
// Bug: res.LastInsertId() does not work for this, so we need to select it manually (how frustrating.)
t . Id , err = db . Conn . SelectInt ( "SELECT id FROM targets WHERE email=?" , t . Email )
2014-02-05 03:08:09 +00:00
if err != nil {
2014-02-06 17:14:51 +00:00
fmt . Printf ( "Error getting id for email: %s\n" , t . Email )
2014-02-05 03:08:09 +00:00
}
_ , err = db . Conn . Exec ( "INSERT OR IGNORE INTO group_targets VALUES (?,?)" , g . Id , t . Id )
if err != nil {
fmt . Printf ( "Error adding many-many mapping for %s\n" , t . Email )
}
}
if checkError ( trans . Commit ( ) , w , "Error committing transaction" ) {
return
}
2014-02-05 00:39:01 +00:00
gj , err := json . MarshalIndent ( g , "" , " " )
if checkError ( err , w , "Error creating JSON response" ) {
return
}
writeJSON ( w , gj )
}
2014-02-02 22:37:36 +00:00
}
// API_Campaigns_Id returns details about the requested campaign. If the campaign is not
// valid, API_Campaigns_Id returns null.
func API_Groups_Id ( w http . ResponseWriter , r * http . Request ) {
http . Redirect ( w , r , "/" , 302 )
}
2014-01-13 02:00:20 +00:00
func writeJSON ( w http . ResponseWriter , c [ ] byte ) {
w . Header ( ) . Set ( "Content-Type" , "application/json" )
fmt . Fprintf ( w , "%s" , c )
}