Updated angular ui to support adding group

Updated POST /api/groups/ to successfully add group
Fixed CSRF in API issue
Moved PUT and DELETE to /api/groups/:id (TODO: Implement)
Changed SQL to use user_id instead of API key
It is now possible to add a new group! Will propagate logic to campaigns soon.
pull/24/head
Jordan 2014-02-09 19:34:47 -06:00
parent 79ba4fadb6
commit b471a886e3
5 changed files with 59 additions and 32 deletions

View File

@ -50,13 +50,10 @@ func API_Reset(w http.ResponseWriter, r *http.Request) {
func API_Campaigns(w http.ResponseWriter, r *http.Request) { func API_Campaigns(w http.ResponseWriter, r *http.Request) {
switch { switch {
case r.Method == "GET": case r.Method == "GET":
cs, err := db.GetCampaigns(ctx.Get(r, "api_key")) cs, err := db.GetCampaigns(ctx.Get(r, "user_id").(int64))
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
} }
/*for c := range cs {
_, err := db.Conn.Select(&cs.Results, "SELECT r.id ")
}*/
cj, err := json.MarshalIndent(cs, "", " ") cj, err := json.MarshalIndent(cs, "", " ")
if checkError(err, w, "Error looking up campaigns") { if checkError(err, w, "Error looking up campaigns") {
return return
@ -96,7 +93,7 @@ func API_Campaigns_Id(w http.ResponseWriter, r *http.Request) {
switch { switch {
case r.Method == "GET": case r.Method == "GET":
c := models.Campaign{} c := models.Campaign{}
c, err := db.GetCampaign(id, ctx.Get(r, "api_key")) c, err := db.GetCampaign(id, ctx.Get(r, "user_id").(int64))
if checkError(err, w, "No campaign found") { if checkError(err, w, "No campaign found") {
return return
} }
@ -140,7 +137,7 @@ RESULT { "name" : "Test Group",
func API_Groups(w http.ResponseWriter, r *http.Request) { func API_Groups(w http.ResponseWriter, r *http.Request) {
switch { switch {
case r.Method == "GET": case r.Method == "GET":
gs, err := db.GetGroups(ctx.Get(r, "api_key")) gs, err := db.GetGroups(ctx.Get(r, "user_id").(int64))
if checkError(err, w, "Cannot retrieve group information") { if checkError(err, w, "Cannot retrieve group information") {
return return
} }
@ -172,9 +169,27 @@ func API_Groups(w http.ResponseWriter, r *http.Request) {
return return
} }
writeJSON(w, gj) writeJSON(w, gj)
case r.Method == "DELETE": }
}
// API_Groups_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) {
vars := mux.Vars(r) vars := mux.Vars(r)
id, _ := strconv.ParseInt(vars["id"], 0, 64) id, _ := strconv.ParseInt(vars["id"], 0, 64)
switch {
case r.Method == "GET":
g := models.Group{}
g, err := db.GetGroup(id, ctx.Get(r, "user_id").(int64))
if checkError(err, w, "No group found") {
return
}
gj, err := json.MarshalIndent(g, "", " ")
if checkError(err, w, "Error creating JSON response") {
return
}
writeJSON(w, gj)
case r.Method == "DELETE":
err := db.DeleteGroup(id) err := db.DeleteGroup(id)
if checkError(err, w, "Error creating JSON response") { if checkError(err, w, "Error creating JSON response") {
return return
@ -183,12 +198,6 @@ func API_Groups(w http.ResponseWriter, r *http.Request) {
} }
} }
// 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)
}
func writeJSON(w http.ResponseWriter, c []byte) { func writeJSON(w http.ResponseWriter, c []byte) {
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
fmt.Fprintf(w, "%s", c) fmt.Fprintf(w, "%s", c)

View File

@ -34,7 +34,7 @@ func CreateRouter() *nosurf.CSRFHandler {
api.HandleFunc("/reset", Use(API_Reset, mid.RequireLogin)) api.HandleFunc("/reset", Use(API_Reset, mid.RequireLogin))
api.HandleFunc("/campaigns/", Use(API_Campaigns, mid.RequireAPIKey)) api.HandleFunc("/campaigns/", Use(API_Campaigns, mid.RequireAPIKey))
api.HandleFunc("/campaigns/{id:[0-9]+}", Use(API_Campaigns_Id, mid.RequireAPIKey)) api.HandleFunc("/campaigns/{id:[0-9]+}", Use(API_Campaigns_Id, mid.RequireAPIKey))
api.HandleFunc("/campaigns/id:[0-9]+}", Use(API_Campaigns_Id_Launch, mid.RequireAPIKey)) //api.HandleFunc("/campaigns/id:[0-9]+}", Use(API_Campaigns_Id_Launch, mid.RequireAPIKey))
api.HandleFunc("/groups/", Use(API_Groups, mid.RequireAPIKey)) api.HandleFunc("/groups/", Use(API_Groups, mid.RequireAPIKey))
api.HandleFunc("/groups/{id:[0-9]+}", Use(API_Groups_Id, mid.RequireAPIKey)) api.HandleFunc("/groups/{id:[0-9]+}", Use(API_Groups_Id, mid.RequireAPIKey))
@ -44,8 +44,8 @@ func CreateRouter() *nosurf.CSRFHandler {
// Setup CSRF Protection // Setup CSRF Protection
csrfHandler := nosurf.New(router) csrfHandler := nosurf.New(router)
// Exempt API routes and Static files // Exempt API routes and Static files
csrfHandler.ExemptGlob("/api/campaigns*") csrfHandler.ExemptGlob("/api/campaigns/*")
csrfHandler.ExemptGlob("/api/groups*") csrfHandler.ExemptGlob("/api/groups/*")
csrfHandler.ExemptGlob("/static/*") csrfHandler.ExemptGlob("/static/*")
return csrfHandler return csrfHandler
} }

View File

@ -114,15 +114,15 @@ func PutUser(u *models.User) error {
return err return err
} }
func GetCampaigns(key interface{}) ([]models.Campaign, error) { func GetCampaigns(uid int64) ([]models.Campaign, error) {
cs := []models.Campaign{} cs := []models.Campaign{}
_, err := 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=?", key) _, err := 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.id=?", uid)
return cs, err return cs, err
} }
func GetCampaign(id int64, key interface{}) (models.Campaign, error) { func GetCampaign(id int64, uid int64) (models.Campaign, error) {
c := models.Campaign{} 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) err := Conn.SelectOne(&c, "SELECT c.id, name, created_date, completed_date, status, template FROM campaigns c, users u WHERE c.uid=u.id AND c.id =? AND u.id=?", id, uid)
return c, err return c, err
} }
@ -131,9 +131,9 @@ func PutCampaign(c *models.Campaign) error {
return err return err
} }
func GetGroups(key interface{}) ([]models.Group, error) { func GetGroups(uid int64) ([]models.Group, error) {
gs := []models.Group{} gs := []models.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.api_key=?", key) _, 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 { if err != nil {
Logger.Println(err) Logger.Println(err)
return gs, err return gs, err
@ -147,6 +147,20 @@ func GetGroups(key interface{}) ([]models.Group, error) {
return gs, nil return gs, nil
} }
func GetGroup(id int64, uid int64) (models.Group, error) {
g := models.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)
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)
if err != nil {
Logger.Println(err)
}
return g, nil
}
func PostGroup(g *models.Group, uid int64) error { func PostGroup(g *models.Group, uid int64) error {
// Insert into the DB // Insert into the DB
err = Conn.Insert(g) err = Conn.Insert(g)

View File

@ -11,9 +11,7 @@ app.factory('CampaignService', function($resource) {
}); });
app.factory('GroupService', function($resource) { app.factory('GroupService', function($resource) {
return $resource('/api/groups/:id?api_key=' + API_KEY, { return $resource('/api/groups/:id?api_key=' + API_KEY, {}, {
id: "@id"
}, {
update: { update: {
method: 'PUT' method: 'PUT'
} }
@ -57,4 +55,15 @@ app.controller('GroupCtrl', function($scope, GroupService) {
$scope.removeTarget = function(target) { $scope.removeTarget = function(target) {
$scope.group.targets.splice($scope.group.targets.indexOf(target), 1); $scope.group.targets.splice($scope.group.targets.indexOf(target), 1);
}; };
$scope.saveGroup = function(group) {
var newGroup = new GroupService($scope.group);
if ($scope.newGroup) {
newGroup.$save(function() {
$scope.groups.push(newGroup);
});
}
else {
newGroup.$update()
}
}
}) })

View File

@ -90,11 +90,6 @@
</form> </form>
<br /> <br />
<table ng-table class="table table-hover table-striped table-condensed"> <table ng-table class="table table-hover table-striped table-condensed">
<thead>
<tr>
<th style="padding-left:0px; border:0;" class="col-sm-2">Members</th>
</tr>
</thead>
<tbody> <tbody>
<tr ng-repeat="target in group.targets" class="editable-row"> <tr ng-repeat="target in group.targets" class="editable-row">
<td>{{target.email}} <td>{{target.email}}
@ -107,7 +102,7 @@
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button> <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary" type="submit">Save Group</button> <button type="button" class="btn btn-primary" ng-click="saveGroup(group)" data-dismiss="modal">Save Group</button>
</div> </div>
</div> </div>
</div> </div>