The great documentation and exported interface cleanup.
Modify all our *Store interfaces to be unexported, as there's no real good
reason they need to be exported, especially as they can be implemented without
being exported. The interfaces shouldn't matter to 99% of users of the package,
so let's not pollute our package API.
Further, all methods of the interfaces are now unexported, for pretty much the
same reasoning.
Add a doc.go file with documentation explaining the choices the package is
making and what it provides.
Implement documentation on all our exported types and methods and functions,
which makes golint happy. The only remaining golint warning is about
NewMemstore, which will stay the way it is. The memstore type is useful outside
tests for things like standing up a server quickly when we don't care about the
storage, and because the type is unexported, we _need_ a New function to create
an instance that can be passed to the Context.
11 "code.secondbit.org/uuid"
21 func TestGetGrantCodeSuccess(t *testing.T) {
23 store := NewMemstore()
24 testContext := Context{
25 template: template.Must(template.New(getGrantTemplateName).Parse("Get auth grant")),
33 Secret: "super secret!",
34 OwnerID: uuid.NewID(),
35 Name: "My test client",
36 Logo: "https://secondbit.org/logo.png",
37 Website: "https://secondbit.org",
40 uri, err := url.Parse("https://test.secondbit.org/redirect")
42 t.Fatal("Can't parse URL:", err)
50 err = testContext.SaveClient(client)
52 t.Fatal("Can't store client:", err)
54 err = testContext.AddEndpoint(client.ID, endpoint)
56 t.Fatal("Can't store endpoint:", err)
58 req, err := http.NewRequest("GET", "https://test.auth.secondbit.org/oauth2/grant", nil)
60 t.Fatal("Can't build request:", err)
62 for i := 0; i < 1<<4; i++ {
63 w := httptest.NewRecorder()
64 params := url.Values{}
65 // see OAuth 2.0 spec, section 4.1.1
66 params.Set("response_type", "code")
67 params.Set("client_id", client.ID.String())
70 params.Set("redirect_uri", endpoint.URI.String())
72 params.Set("redirect_uri", endpoint.URI.String()+"/inexact")
76 params.Set("scope", "testscope")
79 params.Set("state", "my super secure state string")
81 req.URL.RawQuery = params.Encode()
82 GetGrantHandler(w, req, testContext)
83 if w.Code != http.StatusOK {
84 t.Errorf("Expected status code to be %d, got %d for %s", http.StatusOK, w.Code, req.URL.String())
86 if w.Body.String() != "Get auth grant" {
87 t.Errorf("Expected body to be `%s`, got `%s` for %s", "Get auth grant", w.Body.String(), req.URL.String())
92 func TestGetGrantCodeInvalidURI(t *testing.T) {
94 store := NewMemstore()
95 testContext := Context{
96 template: template.Must(template.New(getGrantTemplateName).Parse("{{ .error }}")),
104 Secret: "super secret!",
105 OwnerID: uuid.NewID(),
106 Name: "My test client",
109 uri, err := url.Parse("https://test.secondbit.org/redirect")
111 t.Fatal("Can't parse URL:", err)
113 endpoint := Endpoint{
119 err = testContext.SaveClient(client)
121 t.Fatal("Can't store client:", err)
123 err = testContext.AddEndpoint(client.ID, endpoint)
125 t.Fatal("Can't store endpoint:", err)
127 req, err := http.NewRequest("GET", "https://test.auth.secondbit.org/oauth2/grant", nil)
129 t.Fatal("Can't build request:", err)
131 w := httptest.NewRecorder()
132 params := url.Values{}
133 params.Set("response_type", "code")
134 params.Set("client_id", client.ID.String())
135 params.Set("redirect_uri", "https://test.secondbit.org/wrong")
136 req.URL.RawQuery = params.Encode()
137 GetGrantHandler(w, req, testContext)
138 if w.Code != http.StatusBadRequest {
139 t.Errorf("Expected status code to be %d, got %d", http.StatusBadRequest, w.Code)
141 if w.Body.String() != "The redirect_uri specified is not valid." {
142 t.Errorf(`Expected output to be "%s", got "%s" instead.`, "The redirect_uri specified is not valid.", w.Body.String())