auth

Paddy 2015-05-17 Child:b0d1b3e39fc8

172:8ecb60d29b0d Go to Latest

auth/client/client.go

Support email verification. The bulk of this commit is auto-modifying files to export variables (mostly our request error types and our response type) so that they can be reused in a Go client for that API. We also implement the beginnings of a Go client for that API, implementing the bare minimum we need for our immediate purposes: the ability to retrieve information about a Login. This, of course, means we need an API endpoint that will return information about a Login, which in turn required us to implement a GetLogin method in our profileStore. Which got in-memory and postgres implementations. That done, we could add the Verification field and Verified field to the Login type, to keep track of whether we've verified the user's ownership of those communication methods (if the Login is, in fact, a communication method). This required us to update sql/postgres_init.sql to account for the new fields we're tracking. It also means that when creating a Login, we had to generate a UUID to use as the Verification field. To make things complete, we needed a verifyLogin method on the profileStore to mark a Login as verified. That, in turn, required an endpoint to control this through the API. While doing so, I lumped things together in an UpdateLogin handler just so we could reuse the endpoint and logic when resending a verification email that may have never reached the user, for whatever reason (the quintessential "send again" button). Finally, we implemented an email_verification listener that will pull email_verification events off NSQ, check for the requisite data integrity, and use mailgun to email out a verification/welcome email.

History
paddy@172 1 package client
paddy@172 2
paddy@172 3 import (
paddy@172 4 "bytes"
paddy@172 5 "encoding/json"
paddy@172 6 "errors"
paddy@172 7 "io"
paddy@172 8 "net/http"
paddy@172 9 "strings"
paddy@172 10
paddy@172 11 "code.secondbit.org/auth.hg"
paddy@172 12 )
paddy@172 13
paddy@172 14 var (
paddy@172 15 ErrNilClient = errors.New("nil client wrapper")
paddy@172 16 ErrNilHTTPClient = errors.New("nil client")
paddy@172 17 )
paddy@172 18
paddy@172 19 type Client struct {
paddy@172 20 client *http.Client
paddy@172 21 address string
paddy@172 22 }
paddy@172 23
paddy@172 24 func New(address string) *Client {
paddy@172 25 address = strings.TrimRight(address, "/")
paddy@172 26 return &Client{
paddy@172 27 address: address,
paddy@172 28 client: &http.Client{},
paddy@172 29 }
paddy@172 30 }
paddy@172 31
paddy@172 32 func (c *Client) do(method, url string, request interface{}) (auth.Response, error) {
paddy@172 33 if c == nil {
paddy@172 34 return auth.Response{}, ErrNilClient
paddy@172 35 }
paddy@172 36 if c.client == nil {
paddy@172 37 return auth.Response{}, ErrNilHTTPClient
paddy@172 38 }
paddy@172 39 var response auth.Response
paddy@172 40 if !strings.HasPrefix(url, "http") {
paddy@172 41 url = strings.TrimLeft(url, "/")
paddy@172 42 url = "/" + url
paddy@172 43 url = c.address + url
paddy@172 44 }
paddy@172 45 var body io.Reader
paddy@172 46 if request != nil {
paddy@172 47 data, err := json.Marshal(request)
paddy@172 48 if err != nil {
paddy@172 49 return response, err
paddy@172 50 }
paddy@172 51 body = bytes.NewBuffer(data)
paddy@172 52 }
paddy@172 53 req, err := http.NewRequest(method, url, body)
paddy@172 54 if err != nil {
paddy@172 55 return response, err
paddy@172 56 }
paddy@172 57 resp, err := c.client.Do(req)
paddy@172 58 if err != nil {
paddy@172 59 return response, err
paddy@172 60 }
paddy@172 61 defer resp.Body.Close()
paddy@172 62 switch resp.Header.Get("Content-Type") {
paddy@172 63 case "application/json":
paddy@172 64 dec := json.NewDecoder(resp.Body)
paddy@172 65 err = dec.Decode(&response)
paddy@172 66 if err != nil {
paddy@172 67 return response, err
paddy@172 68 }
paddy@172 69 default:
paddy@172 70 dec := json.NewDecoder(resp.Body)
paddy@172 71 err = dec.Decode(&response)
paddy@172 72 if err != nil {
paddy@172 73 return response, err
paddy@172 74 }
paddy@172 75 }
paddy@172 76 return response, nil
paddy@172 77 }
paddy@172 78
paddy@172 79 func (c *Client) Get(url string) (auth.Response, error) {
paddy@172 80 return c.do("GET", url, nil)
paddy@172 81 }