- Working on implementing the API (started working on /api/campaigns)

- Implemented APIKey middleware
- Changed settings template to look a bit nicer and to, you know, work.
This commit is contained in:
Jordan 2014-01-30 22:46:25 -06:00
parent e9aa8d2c88
commit c60b9d584b
6 changed files with 84 additions and 19 deletions

View file

@ -7,9 +7,18 @@ import (
ctx "github.com/gorilla/context"
"github.com/gorilla/mux"
"github.com/jordan-wright/gophish/db"
"github.com/jordan-wright/gophish/models"
)
func API(w http.ResponseWriter, r *http.Request) {
if r.Method == "GET" {
}
if r.Method == "POST" {
//Add a new campaign
//v :=
}
if u, err := json.Marshal(ctx.Get(r, "user")); err == nil {
writeJSON(w, u)
} else {
@ -20,10 +29,18 @@ func API(w http.ResponseWriter, r *http.Request) {
//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.
func API_Campaigns(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
switch {
case r.Method == "GET":
cs := []models.Campaign{}
_, err := db.Conn.Select(&cs, "SELECT name, created_date, completed_date, status, template FROM campaigns, users WHERE campaigns.uid=users.id AND users.apikey=?", ctx.Get(r, "api_key"))
if err != nil {
fmt.Println(err)
}
d, err := json.Marshal(cs)
if err != nil {
fmt.Println(err)
}
writeJSON(w, d)
case r.Method == "POST":
fmt.Fprintf(w, "Hello POST!")
}

View file

@ -52,9 +52,9 @@ func CreateRouter() *mux.Router {
// Create the API routes
api := router.PathPrefix("/api").Subrouter()
api.HandleFunc("/", Use(API, mid.RequireLogin))
api.HandleFunc("/campaigns", API_Campaigns)
api.HandleFunc("/campaigns/{id}", API_Campaigns_Id)
api.HandleFunc("/", Use(API, mid.RequireAPIKey))
api.HandleFunc("/campaigns", Use(API_Campaigns, mid.RequireAPIKey))
api.HandleFunc("/campaigns/{id}", Use(API_Campaigns_Id, mid.RequireAPIKey))
api.HandleFunc("/doc", API_Doc)
//Setup static file serving
@ -121,14 +121,10 @@ func Login(w http.ResponseWriter, r *http.Request) {
getTemplate(w, "login").ExecuteTemplate(w, "base", params)
case r.Method == "POST":
//Attempt to login
if err := r.ParseForm(); err != nil {
http.Error(w, "Error parsing request", http.StatusInternalServerError)
}
err := r.ParseForm()
checkError(err, w, "Error parsing request")
succ, err := auth.Login(r)
if err != nil {
fmt.Println(err)
http.Error(w, "Error logging in", http.StatusInternalServerError)
}
checkError(err, w, "Error logging in")
//If we've logged in, save the session and redirect to the dashboard
if succ {
session.Save(r, w)
@ -147,3 +143,10 @@ func Login(w http.ResponseWriter, r *http.Request) {
func getTemplate(w http.ResponseWriter, tmpl string) *template.Template {
return template.Must(template.New("template").ParseFiles("templates/base.html", "templates/nav.html", "templates/"+tmpl+".html", "templates/flashes.html"))
}
func checkError(e error, w http.ResponseWriter, m string) {
if e != nil {
fmt.Println(e)
http.Error(w, m, http.StatusInternalServerError)
}
}

View file

@ -4,6 +4,7 @@ import (
"database/sql"
"fmt"
"os"
"time"
"github.com/coopernurse/gorp"
"github.com/jordan-wright/gophish/config"
@ -28,8 +29,8 @@ func Setup() error {
fmt.Println("Database not found, recreating...")
createTablesSQL := []string{
//Create tables
`CREATE TABLE Users (id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT NOT NULL, hash VARCHAR(60) NOT NULL, apikey VARCHAR(32));`,
`CREATE TABLE Campaigns (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, created_date TEXT NOT NULL, completed_date TEXT, template TEXT, status TEXT NOT NULL, uid INTEGER, FOREIGN KEY (uid) REFERENCES Users(id));`,
`CREATE TABLE users (id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT NOT NULL, hash VARCHAR(60) NOT NULL, apikey VARCHAR(32));`,
`CREATE TABLE campaigns (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, created_date TIMESTAMP NOT NULL, completed_date TIMESTAMP, template TEXT, status TEXT NOT NULL, uid INTEGER, FOREIGN KEY (uid) REFERENCES Users(id));`,
}
fmt.Println("Creating db at " + config.Conf.DBPath)
//Create the tables needed
@ -49,6 +50,15 @@ func Setup() error {
if err != nil {
fmt.Println(err)
}
c := models.Campaign{
Name: "Test Campaigns",
CreatedDate: time.Now().UTC(),
CompletedDate: time.Now().UTC(),
Template: "test template",
Status: "In progress",
Uid: init_user.Id,
}
Conn.Insert(&c)
}
return nil
}

View file

@ -32,6 +32,19 @@ func GetContext(handler http.Handler) http.HandlerFunc {
}
}
func RequireAPIKey(handler http.Handler) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
ak := r.Form.Get("api_key")
if ak == "" {
JSONError(w, 500, "API Key not set")
} else {
ctx.Set(r, "api_key", ak)
handler.ServeHTTP(w, r)
}
}
}
// RequireLogin is a simple middleware which checks to see if the user is currently logged in.
// If not, the function returns a 302 redirect to the login page.
func RequireLogin(handler http.Handler) http.HandlerFunc {
@ -43,3 +56,7 @@ func RequireLogin(handler http.Handler) http.HandlerFunc {
}
}
}
func JSONError(w http.ResponseWriter, c int, m string) {
http.Error(w, m, c)
}

View file

@ -42,7 +42,7 @@ type Campaign struct {
CompletedDate time.Time `json:"completed_date" db:"completed_date"`
Template string `json:"template"` //This may change
Status string `json:"status"`
Uid int
Uid int `json:"-"`
}
type UserCampaigns struct {

View file

@ -20,10 +20,28 @@
</ul>
</div>
<div class="col-md-9 sans">
<h1 style="margin-top:0px">User Settings</h1>
<p><b>Username:</b> {{.User.Username}}</p>
<p><b>Api Key:</b> {{.User.APIKey}}</p>
<h1 style="margin:0px 0px 15px 0px;">User Settings</h1>
<div class="row">
<div class="col-md-2">
<p><b>Username:</b>
</p>
</div>
<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" value="{{.User.APIKey}}" class="form-control" readonly/>
</div>
</div>
<br />
<button class="btn btn-primary">Save</button>
</div>
</div>
{{end}}