From b269cf2861ee8ea7553055e1a6affe01298c956e Mon Sep 17 00:00:00 2001 From: Piotr Zduniak Date: Sun, 16 Nov 2014 18:01:11 +0100 Subject: [PATCH 1/7] Added GET /contacts --- db/table_accounts.go | 15 +++++++++++++++ db/table_contacts.go | 42 ++++++++++++++++++++++++++++++++++++++++++ db/table_tokens.go | 4 ++-- env/env.go | 2 ++ main.go | 16 ++++++++++++---- routes/accounts.go | 18 +++--------------- routes/contacts.go | 33 ++++++++++++++++++++++++++++----- 7 files changed, 104 insertions(+), 26 deletions(-) create mode 100644 db/table_contacts.go diff --git a/db/table_accounts.go b/db/table_accounts.go index d7a1ee9..0cc86f1 100644 --- a/db/table_accounts.go +++ b/db/table_accounts.go @@ -1,12 +1,16 @@ package db import ( + "errors" + "github.com/lavab/api/models" ) // AccountsTable implements the CRUD interface for accounts type AccountsTable struct { RethinkCRUD + + Tokens *TokensTable } // GetAccount returns an account with specified ID @@ -30,3 +34,14 @@ func (users *AccountsTable) FindAccountByName(name string) (*models.Account, err return &result, nil } + +func (a *AccountsTable) GetTokenOwner(token *models.Token) (*models.Account, error) { + user, err := a.GetAccount(token.Owner) + if err != nil { + // Try to remove the orphaned token + a.Tokens.DeleteID(token.ID) + return nil, errors.New("Account disabled") + } + + return user, nil +} diff --git a/db/table_contacts.go b/db/table_contacts.go new file mode 100644 index 0000000..5391fc0 --- /dev/null +++ b/db/table_contacts.go @@ -0,0 +1,42 @@ +package db + +import ( + "github.com/lavab/api/models" +) + +// Contacts implements the CRUD interface for tokens +type ContactsTable struct { + RethinkCRUD +} + +// GetContact returns a token with specified name +func (c *ContactsTable) GetContact(id string) (*models.Contact, error) { + var result models.Contact + + if err := c.FindFetchOne(id, &result); err != nil { + return nil, err + } + + return &result, nil +} + +// GetOwnedBy returns all contacts owned by id +func (c *ContactsTable) GetOwnedBy(id string) ([]*models.Contact, error) { + var result []*models.Contact + + err := c.WhereAndFetch(map[string]interface{}{ + "owner": id, + }, &result) + if err != nil { + return nil, err + } + + return result, nil +} + +// DeleteOwnedBy deletes all contacts owned by id +func (c *ContactsTable) DeleteOwnedBy(id string) error { + return c.Delete(map[string]interface{}{ + "owner": id, + }) +} diff --git a/db/table_tokens.go b/db/table_tokens.go index 83f54f0..8de409e 100644 --- a/db/table_tokens.go +++ b/db/table_tokens.go @@ -20,8 +20,8 @@ func (t *TokensTable) GetToken(id string) (*models.Token, error) { return &result, nil } -// DeleteByOwner deletes all tokens owned by id -func (t *TokensTable) DeleteByOwner(id string) error { +// DeleteOwnedBy deletes all tokens owned by id +func (t *TokensTable) DeleteOwnedBy(id string) error { return t.Delete(map[string]interface{}{ "owner": id, }) diff --git a/env/env.go b/env/env.go index bd05854..18178b6 100644 --- a/env/env.go +++ b/env/env.go @@ -20,4 +20,6 @@ var ( Tokens *db.TokensTable // Keys is the global instance of KeysTable Keys *db.KeysTable + // Contacts is the global instance of ContactsTable + Contacts *db.ContactsTable ) diff --git a/main.go b/main.go index 9cbcef4..1ef2346 100644 --- a/main.go +++ b/main.go @@ -104,19 +104,20 @@ func main() { env.Rethink = rethinkSession // Initialize the tables - env.Accounts = &db.AccountsTable{ + env.Tokens = &db.TokensTable{ RethinkCRUD: db.NewCRUDTable( rethinkSession, rethinkOpts.Database, - "accounts", + "tokens", ), } - env.Tokens = &db.TokensTable{ + env.Accounts = &db.AccountsTable{ RethinkCRUD: db.NewCRUDTable( rethinkSession, rethinkOpts.Database, - "tokens", + "accounts", ), + Tokens: env.Tokens, } env.Keys = &db.KeysTable{ RethinkCRUD: db.NewCRUDTable( @@ -125,6 +126,13 @@ func main() { "keys", ), } + env.Contacts = &db.ContactsTable{ + RethinkCRUD: db.NewCRUDTable( + rethinkSession, + rethinkOpts.Database, + "contacts", + ), + } // Create a new goji mux mux := web.New() diff --git a/routes/accounts.go b/routes/accounts.go index 7b77b64..e0576a5 100644 --- a/routes/accounts.go +++ b/routes/accounts.go @@ -478,7 +478,7 @@ func AccountsDelete(c web.C, w http.ResponseWriter, r *http.Request) { // TODO: Delete threads // Delete tokens - err = env.Tokens.DeleteByOwner(user.ID) + err = env.Tokens.DeleteOwnedBy(user.ID) if err != nil { env.Log.WithFields(logrus.Fields{ "id": user.ID, @@ -543,7 +543,7 @@ func AccountsWipeData(c web.C, w http.ResponseWriter, r *http.Request) { session := c.Env["session"].(*models.Token) // Fetch the user object from the database - user, err := env.Accounts.GetAccount(session.Owner) + user, err := env.Accounts.GetTokenOwner(session) if err != nil { // The session refers to a non-existing user env.Log.WithFields(logrus.Fields{ @@ -551,18 +551,6 @@ func AccountsWipeData(c web.C, w http.ResponseWriter, r *http.Request) { "error": err, }).Warn("Valid session referred to a removed account") - // Try to remove the orphaned session - if err := env.Tokens.DeleteID(session.ID); err != nil { - env.Log.WithFields(logrus.Fields{ - "id": session.ID, - "error": err, - }).Error("Unable to remove an orphaned session") - } else { - env.Log.WithFields(logrus.Fields{ - "id": session.ID, - }).Info("Removed an orphaned session") - } - utils.JSONResponse(w, 410, &AccountsWipeDataResponse{ Success: false, Message: "Account disabled", @@ -579,7 +567,7 @@ func AccountsWipeData(c web.C, w http.ResponseWriter, r *http.Request) { // TODO: Delete threads // Delete tokens - err = env.Tokens.DeleteByOwner(user.ID) + err = env.Tokens.DeleteOwnedBy(user.ID) if err != nil { env.Log.WithFields(logrus.Fields{ "id": user.ID, diff --git a/routes/contacts.go b/routes/contacts.go index d0effbf..10e52bb 100644 --- a/routes/contacts.go +++ b/routes/contacts.go @@ -3,20 +3,43 @@ package routes import ( "net/http" + "github.com/Sirupsen/logrus" + "github.com/zenazn/goji/web" + + "github.com/lavab/api/env" + "github.com/lavab/api/models" "github.com/lavab/api/utils" ) // ContactsListResponse contains the result of the ContactsList request. type ContactsListResponse struct { - Success bool `json:"success"` - Message string `json:"message"` + Success bool `json:"success"` + Message string `json:"message,omitempty"` + Contacts *[]*models.Contact `json:"contacts,omitempty"` } // ContactsList does *something* - TODO -func ContactsList(w http.ResponseWriter, r *http.Request) { +func ContactsList(c web.C, w http.ResponseWriter, r *http.Request) { + // Fetch the current session from the database + session := c.Env["session"].(*models.Token) + + // Get contacts from the database + contacts, err := env.Contacts.GetOwnedBy(session.Owner) + if err != nil { + env.Log.WithFields(logrus.Fields{ + "error": err, + }).Error("Unable to fetch contacts") + + utils.JSONResponse(w, 500, &AccountsDeleteResponse{ + Success: false, + Message: "Internal error (code CO/LI/01)", + }) + return + } + utils.JSONResponse(w, 501, &ContactsListResponse{ - Success: false, - Message: "Sorry, not implemented yet", + Success: false, + Contacts: &contacts, }) } From 9e86de497b574f42a6079519249f87dbf4ccf135 Mon Sep 17 00:00:00 2001 From: Piotr Zduniak Date: Sun, 16 Nov 2014 18:21:50 +0100 Subject: [PATCH 2/7] Added basic request structs for /contacts --- routes/contacts.go | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/routes/contacts.go b/routes/contacts.go index 10e52bb..f91928b 100644 --- a/routes/contacts.go +++ b/routes/contacts.go @@ -43,6 +43,14 @@ func ContactsList(c web.C, w http.ResponseWriter, r *http.Request) { }) } +type ContactsCreateRequest struct { + Data string `json:"data" schema:"data"` + Name string `json:"name" schema:"name"` + Encoding string `json:"encoding" schema:"encoding"` + VersionMajor int `json:"version_major" schema:"version_major"` + VersionMinor int `json:"version_minor" schema:"version_minor"` +} + // ContactsCreateResponse contains the result of the ContactsCreate request. type ContactsCreateResponse struct { Success bool `json:"success"` @@ -59,8 +67,9 @@ func ContactsCreate(w http.ResponseWriter, r *http.Request) { // ContactsGetResponse contains the result of the ContactsGet request. type ContactsGetResponse struct { - Success bool `json:"success"` - Message string `json:"message"` + Success bool `json:"success"` + Message string `json:"message"` + Contact *models.Contact `json:"contact"` } // ContactsGet does *something* - TODO @@ -71,6 +80,14 @@ func ContactsGet(w http.ResponseWriter, r *http.Request) { }) } +type ContactsUpdateRequest struct { + Data string `json:"data" schema:"data"` + Name string `json:"name" schema:"name"` + Encoding string `json:"encoding" schema:"encoding"` + VersionMajor int `json:"version_major" schema:"version_major"` + VersionMinor int `json:"version_minor" schema:"version_minor"` +} + // ContactsUpdateResponse contains the result of the ContactsUpdate request. type ContactsUpdateResponse struct { Success bool `json:"success"` From 5685866f569b7c5842b07d6679e9b17cc48e2439 Mon Sep 17 00:00:00 2001 From: Piotr Zduniak Date: Sun, 16 Nov 2014 21:27:38 +0100 Subject: [PATCH 3/7] Implemented POST /contacts --- models/base_encrypted.go | 2 +- routes/accounts.go | 2 +- routes/contacts.go | 73 +++++++++++++++++++++++++++++++++++----- 3 files changed, 66 insertions(+), 11 deletions(-) diff --git a/models/base_encrypted.go b/models/base_encrypted.go index 359f066..44eec0b 100644 --- a/models/base_encrypted.go +++ b/models/base_encrypted.go @@ -9,7 +9,7 @@ type Encrypted struct { PgpFingerprints []string `json:"pgp_fingerprints" gorethink:"pgp_fingerprints"` // Data is the raw, PGP-encrypted data - Data []byte `json:"raw" gorethink:"raw"` + Data string `json:"raw" gorethink:"raw"` // Schema is the name of the schema used to encode the data // Examples: string, contact, email diff --git a/routes/accounts.go b/routes/accounts.go index e0576a5..a98e023 100644 --- a/routes/accounts.go +++ b/routes/accounts.go @@ -183,7 +183,7 @@ func AccountsCreate(w http.ResponseWriter, r *http.Request) { env.Log.WithFields(logrus.Fields{ "error": err, - }).Error("Could not insert an user to the database") + }).Error("Could not insert an user into the database") return } diff --git a/routes/contacts.go b/routes/contacts.go index f91928b..881500c 100644 --- a/routes/contacts.go +++ b/routes/contacts.go @@ -43,25 +43,80 @@ func ContactsList(c web.C, w http.ResponseWriter, r *http.Request) { }) } +// ContactsCreateRequest is the payload that user should pass to POST /contacts type ContactsCreateRequest struct { Data string `json:"data" schema:"data"` Name string `json:"name" schema:"name"` Encoding string `json:"encoding" schema:"encoding"` - VersionMajor int `json:"version_major" schema:"version_major"` - VersionMinor int `json:"version_minor" schema:"version_minor"` + VersionMajor *int `json:"version_major" schema:"version_major"` + VersionMinor *int `json:"version_minor" schema:"version_minor"` } // ContactsCreateResponse contains the result of the ContactsCreate request. type ContactsCreateResponse struct { - Success bool `json:"success"` - Message string `json:"message"` + Success bool `json:"success"` + Message string `json:"message"` + Contact *models.Contact `json:"contact,omitempty"` } -// ContactsCreate does *something* - TODO -func ContactsCreate(w http.ResponseWriter, r *http.Request) { - utils.JSONResponse(w, 501, &ContactsCreateResponse{ - Success: false, - Message: "Sorry, not implemented yet", +// ContactsCreate creates a new contact +func ContactsCreate(c web.C, w http.ResponseWriter, r *http.Request) { + // Decode the request + var input ContactsCreateRequest + err := utils.ParseRequest(r, &input) + if err != nil { + env.Log.WithFields(logrus.Fields{ + "error": err, + }).Warn("Unable to decode a request") + + utils.JSONResponse(w, 400, &ContactsCreateResponse{ + Success: false, + Message: "Invalid input format", + }) + return + } + + // Fetch the current session from the database + session := c.Env["session"].(*models.Token) + + // Ensure that the input data isn't empty + if input.Data != "" || input.Name != "" || input.Encoding != "" || input.VersionMajor != nil || input.VersionMinor != nil { + utils.JSONResponse(w, 400, &ContactsCreateResponse{ + Success: false, + Message: "Invalid request", + }) + return + } + + // Create a new contact struct + contact := &models.Contact{ + Encrypted: models.Encrypted{ + Encoding: input.Encoding, + Data: input.Data, + Schema: "contact", + VersionMajor: *input.VersionMajor, + VersionMinor: *input.VersionMinor, + }, + Resource: models.MakeResource(session.Owner, input.Name), + } + + // Insert the contact into the database + if err := env.Contacts.Insert(contact); err != nil { + utils.JSONResponse(w, 500, &ContactsCreateResponse{ + Success: false, + Message: "internal server error - CO/CR/01", + }) + + env.Log.WithFields(logrus.Fields{ + "error": err, + }).Error("Could not insert a contact into the database") + return + } + + utils.JSONResponse(w, 201, &ContactsCreateResponse{ + Success: true, + Message: "A new account was successfully created", + Contact: contact, }) } From 2e6efa21ca3a739a323d7fc8ade66332cd98a5ce Mon Sep 17 00:00:00 2001 From: Piotr Zduniak Date: Sun, 16 Nov 2014 21:48:10 +0100 Subject: [PATCH 4/7] Added GET /contacts/:id --- routes/contacts.go | 39 +++++++++++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/routes/contacts.go b/routes/contacts.go index 881500c..9221259 100644 --- a/routes/contacts.go +++ b/routes/contacts.go @@ -76,7 +76,7 @@ func ContactsCreate(c web.C, w http.ResponseWriter, r *http.Request) { return } - // Fetch the current session from the database + // Fetch the current session from the middleware session := c.Env["session"].(*models.Token) // Ensure that the input data isn't empty @@ -123,15 +123,38 @@ func ContactsCreate(c web.C, w http.ResponseWriter, r *http.Request) { // ContactsGetResponse contains the result of the ContactsGet request. type ContactsGetResponse struct { Success bool `json:"success"` - Message string `json:"message"` - Contact *models.Contact `json:"contact"` + Message string `json:"message,omitempty"` + Contact *models.Contact `json:"contact,omitempty"` } -// ContactsGet does *something* - TODO -func ContactsGet(w http.ResponseWriter, r *http.Request) { - utils.JSONResponse(w, 501, &ContactsGetResponse{ - Success: false, - Message: "Sorry, not implemented yet", +// ContactsGet gets the requested contact from the database +func ContactsGet(c web.C, w http.ResponseWriter, r *http.Request) { + // Get the contact from the database + contact, err := env.Contacts.GetContact(c.URLParams["id"]) + if err != nil { + utils.JSONResponse(w, 404, &ContactsGetResponse{ + Success: false, + Message: "Contact not found", + }) + return + } + + // Fetch the current session from the middleware + session := c.Env["session"].(*models.Token) + + // Check for ownership + if contact.Owner != session.Owner { + utils.JSONResponse(w, 404, &ContactsGetResponse{ + Success: false, + Message: "Contact not found", + }) + return + } + + // Write the contact to the response + utils.JSONResponse(w, 200, &ContactsGetResponse{ + Success: true, + Contact: contact, }) } From 534f6da20d1bd6f625f04f94bf2f6c4946935f04 Mon Sep 17 00:00:00 2001 From: Piotr Zduniak Date: Sun, 16 Nov 2014 21:56:32 +0100 Subject: [PATCH 5/7] Implemented PUT /contacts/:id --- routes/contacts.go | 82 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 75 insertions(+), 7 deletions(-) diff --git a/routes/contacts.go b/routes/contacts.go index 9221259..169aa13 100644 --- a/routes/contacts.go +++ b/routes/contacts.go @@ -158,6 +158,7 @@ func ContactsGet(c web.C, w http.ResponseWriter, r *http.Request) { }) } +// ContactsUpdateRequest is the payload passed to PUT /contacts/:id type ContactsUpdateRequest struct { Data string `json:"data" schema:"data"` Name string `json:"name" schema:"name"` @@ -168,15 +169,82 @@ type ContactsUpdateRequest struct { // ContactsUpdateResponse contains the result of the ContactsUpdate request. type ContactsUpdateResponse struct { - Success bool `json:"success"` - Message string `json:"message"` + Success bool `json:"success"` + Message string `json:"message,omitempty"` + Contact *models.Contact `json:"contact,omitempty"` } -// ContactsUpdate does *something* - TODO -func ContactsUpdate(w http.ResponseWriter, r *http.Request) { - utils.JSONResponse(w, 501, &ContactsUpdateResponse{ - Success: false, - Message: "Sorry, not implemented yet", +// ContactsUpdate updates an existing contact in the database +func ContactsUpdate(c web.C, w http.ResponseWriter, r *http.Request) { + // Decode the request + var input ContactsUpdateRequest + err := utils.ParseRequest(r, &input) + if err != nil { + env.Log.WithFields(logrus.Fields{ + "error": err, + }).Warn("Unable to decode a request") + + utils.JSONResponse(w, 400, &ContactsUpdateResponse{ + Success: false, + Message: "Invalid input format", + }) + return + } + + // Get the contact from the database + contact, err := env.Contacts.GetContact(c.URLParams["id"]) + if err != nil { + utils.JSONResponse(w, 404, &ContactsUpdateResponse{ + Success: false, + Message: "Contact not found", + }) + return + } + + // Fetch the current session from the middleware + session := c.Env["session"].(*models.Token) + + // Check for ownership + if contact.Owner != session.Owner { + utils.JSONResponse(w, 404, &ContactsUpdateResponse{ + Success: false, + Message: "Contact not found", + }) + return + } + + // Perform the update + err = env.Contacts.UpdateID(c.URLParams["id"], map[string]interface{}{ + "data": input.Data, + "name": input.Name, + "encoding": input.Encoding, + "version_major": input.VersionMajor, + "version_minor": input.VersionMinor, + }) + if err != nil { + env.Log.WithFields(logrus.Fields{ + "error": err, + "id": c.URLParams["id"], + }).Error("Unable to update a contact") + + utils.JSONResponse(w, 500, &ContactsUpdateResponse{ + Success: false, + Message: "Internal error (code CO/UP/01)", + }) + return + } + + // Update the original struct for the response + contact.Data = input.Data + contact.Name = input.Name + contact.Encoding = input.Encoding + contact.VersionMajor = input.VersionMajor + contact.VersionMinor = input.VersionMinor + + // Write the contact to the response + utils.JSONResponse(w, 200, &ContactsUpdateResponse{ + Success: true, + Contact: contact, }) } From 18f10ec3dcaffe30722b7b2afdf42313a849f0be Mon Sep 17 00:00:00 2001 From: Piotr Zduniak Date: Sun, 16 Nov 2014 21:57:53 +0100 Subject: [PATCH 6/7] Changed c.Env["session"] to c.Env["token"] --- routes/accounts.go | 8 ++++---- routes/contacts.go | 8 ++++---- routes/keys.go | 2 +- routes/middleware.go | 2 +- routes/tokens.go | 4 ++-- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/routes/accounts.go b/routes/accounts.go index a98e023..eaf9618 100644 --- a/routes/accounts.go +++ b/routes/accounts.go @@ -247,7 +247,7 @@ func AccountsGet(c web.C, w http.ResponseWriter, r *http.Request) { } // Fetch the current session from the database - session := c.Env["session"].(*models.Token) + session := c.Env["token"].(*models.Token) // Fetch the user object from the database user, err := env.Accounts.GetAccount(session.Owner) @@ -336,7 +336,7 @@ func AccountsUpdate(c web.C, w http.ResponseWriter, r *http.Request) { } // Fetch the current session from the database - session := c.Env["session"].(*models.Token) + session := c.Env["token"].(*models.Token) // Fetch the user object from the database user, err := env.Accounts.GetAccount(session.Owner) @@ -439,7 +439,7 @@ func AccountsDelete(c web.C, w http.ResponseWriter, r *http.Request) { } // Fetch the current session from the database - session := c.Env["session"].(*models.Token) + session := c.Env["token"].(*models.Token) // Fetch the user object from the database user, err := env.Accounts.GetAccount(session.Owner) @@ -540,7 +540,7 @@ func AccountsWipeData(c web.C, w http.ResponseWriter, r *http.Request) { } // Fetch the current session from the database - session := c.Env["session"].(*models.Token) + session := c.Env["token"].(*models.Token) // Fetch the user object from the database user, err := env.Accounts.GetTokenOwner(session) diff --git a/routes/contacts.go b/routes/contacts.go index 169aa13..0127241 100644 --- a/routes/contacts.go +++ b/routes/contacts.go @@ -21,7 +21,7 @@ type ContactsListResponse struct { // ContactsList does *something* - TODO func ContactsList(c web.C, w http.ResponseWriter, r *http.Request) { // Fetch the current session from the database - session := c.Env["session"].(*models.Token) + session := c.Env["token"].(*models.Token) // Get contacts from the database contacts, err := env.Contacts.GetOwnedBy(session.Owner) @@ -77,7 +77,7 @@ func ContactsCreate(c web.C, w http.ResponseWriter, r *http.Request) { } // Fetch the current session from the middleware - session := c.Env["session"].(*models.Token) + session := c.Env["token"].(*models.Token) // Ensure that the input data isn't empty if input.Data != "" || input.Name != "" || input.Encoding != "" || input.VersionMajor != nil || input.VersionMinor != nil { @@ -140,7 +140,7 @@ func ContactsGet(c web.C, w http.ResponseWriter, r *http.Request) { } // Fetch the current session from the middleware - session := c.Env["session"].(*models.Token) + session := c.Env["token"].(*models.Token) // Check for ownership if contact.Owner != session.Owner { @@ -202,7 +202,7 @@ func ContactsUpdate(c web.C, w http.ResponseWriter, r *http.Request) { } // Fetch the current session from the middleware - session := c.Env["session"].(*models.Token) + session := c.Env["token"].(*models.Token) // Check for ownership if contact.Owner != session.Owner { diff --git a/routes/keys.go b/routes/keys.go index e0308d4..cbd4fce 100644 --- a/routes/keys.go +++ b/routes/keys.go @@ -88,7 +88,7 @@ func KeysCreate(c web.C, w http.ResponseWriter, r *http.Request) { } // Get the session - session := c.Env["session"].(*models.Token) + session := c.Env["token"].(*models.Token) // Parse the armored key entityList, err := openpgp.ReadArmoredKeyRing(strings.NewReader(input.Key)) diff --git a/routes/middleware.go b/routes/middleware.go index 7ce3317..837ac04 100644 --- a/routes/middleware.go +++ b/routes/middleware.go @@ -65,7 +65,7 @@ func AuthMiddleware(c *web.C, h http.Handler) http.Handler { } // Continue to the next middleware/route - c.Env["session"] = token + c.Env["token"] = token h.ServeHTTP(w, r) }) } diff --git a/routes/tokens.go b/routes/tokens.go index bfc1e8a..54e4ca2 100644 --- a/routes/tokens.go +++ b/routes/tokens.go @@ -23,7 +23,7 @@ type TokensGetResponse struct { // TokensGet returns information about the current token. func TokensGet(c web.C, w http.ResponseWriter, r *http.Request) { // Fetch the current session from the database - session := c.Env["session"].(*models.Token) + session := c.Env["token"].(*models.Token) // Respond with the token information utils.JSONResponse(w, 200, &TokensGetResponse{ @@ -142,7 +142,7 @@ func TokensDelete(c web.C, w http.ResponseWriter, r *http.Request) { id, ok := c.URLParams["id"] if !ok || id == "" { // Get the token from the middleware - token = c.Env["session"].(*models.Token) + token = c.Env["token"].(*models.Token) } else { token, err = env.Tokens.GetToken(id) if err != nil { From 6dd9a45064e5d4503f6f10ab09911703ad5a720c Mon Sep 17 00:00:00 2001 From: Piotr Zduniak Date: Sun, 16 Nov 2014 22:00:43 +0100 Subject: [PATCH 7/7] Added DELETE /contacts/:id --- routes/contacts.go | 48 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 43 insertions(+), 5 deletions(-) diff --git a/routes/contacts.go b/routes/contacts.go index 0127241..5d8e18a 100644 --- a/routes/contacts.go +++ b/routes/contacts.go @@ -254,10 +254,48 @@ type ContactsDeleteResponse struct { Message string `json:"message"` } -// ContactsDelete does *something* - TODO -func ContactsDelete(w http.ResponseWriter, r *http.Request) { - utils.JSONResponse(w, 501, &ContactsDeleteResponse{ - Success: false, - Message: "Sorry, not implemented yet", +// ContactsDelete removes a contact from the database +func ContactsDelete(c web.C, w http.ResponseWriter, r *http.Request) { + // Get the contact from the database + contact, err := env.Contacts.GetContact(c.URLParams["id"]) + if err != nil { + utils.JSONResponse(w, 404, &ContactsDeleteResponse{ + Success: false, + Message: "Contact not found", + }) + return + } + + // Fetch the current session from the middleware + session := c.Env["token"].(*models.Token) + + // Check for ownership + if contact.Owner != session.Owner { + utils.JSONResponse(w, 404, &ContactsDeleteResponse{ + Success: false, + Message: "Contact not found", + }) + return + } + + // Perform the deletion + err = env.Contacts.DeleteID(c.URLParams["id"]) + if err != nil { + env.Log.WithFields(logrus.Fields{ + "error": err, + "id": c.URLParams["id"], + }).Error("Unable to delete a contact") + + utils.JSONResponse(w, 500, &ContactsDeleteResponse{ + Success: false, + Message: "Internal error (code CO/DE/01)", + }) + return + } + + // Write the contact to the response + utils.JSONResponse(w, 200, &ContactsDeleteResponse{ + Success: true, + Message: "Contact successfully removed", }) }