Add an endpoint to validate and register profiles.
Add a newProfileRequest object that defines the user-specified properties of a
new Profile.
Add a helper that validates a newProfileRequest and modifies it for
sanitization, mostly just removing leading and trailing whitespace.
Add MaxNameLength, MaxUsernameLength, and MaxEmailLength constants to hold the
maximum length for those properties.
Add errors to be returned when a users attempts to log in with a profile that is
compromised or locked.
Add the bare bones of a CreateProfileHandler that validates a profile
registration request adn uses it to create a Profile and at least one Login.
Create a requestError struct that is used for returning API errors, along with
constants for the slugs we'll use to signal those errors.
7 "code.secondbit.org/uuid"
10 var authCodeStores = []authorizationCodeStore{NewMemstore()}
12 func compareAuthorizationCodes(authCode1, authCode2 AuthorizationCode) (success bool, field string, authCode1val, authCode2val interface{}) {
13 if authCode1.Code != authCode2.Code {
14 return false, "code", authCode1.Code, authCode2.Code
16 if !authCode1.Created.Equal(authCode2.Created) {
17 return false, "created", authCode1.Created, authCode2.Created
19 if authCode1.ExpiresIn != authCode2.ExpiresIn {
20 return false, "expires in", authCode1.ExpiresIn, authCode2.ExpiresIn
22 if !authCode1.ClientID.Equal(authCode2.ClientID) {
23 return false, "client ID", authCode1.ClientID, authCode2.ClientID
25 if authCode1.Scope != authCode2.Scope {
26 return false, "scope", authCode1.Scope, authCode2.Scope
28 if authCode1.RedirectURI != authCode2.RedirectURI {
29 return false, "redirect URI", authCode1.RedirectURI, authCode2.RedirectURI
31 if authCode1.State != authCode2.State {
32 return false, "state", authCode1.State, authCode2.State
34 return true, "", nil, nil
37 func TestAuthorizationCodeStoreSuccess(t *testing.T) {
39 authCode := AuthorizationCode{
43 ClientID: uuid.NewID(),
45 RedirectURI: "redirectURI",
48 for _, store := range authCodeStores {
49 err := store.saveAuthorizationCode(authCode)
51 t.Errorf("Error saving auth code to %T: %s", store, err)
53 err = store.saveAuthorizationCode(authCode)
54 if err != ErrAuthorizationCodeAlreadyExists {
55 t.Errorf("Expected ErrAuthorizationCodeAlreadyExists from %T, got %+v", store, err)
57 retrieved, err := store.getAuthorizationCode(authCode.Code)
59 t.Errorf("Error retrieving auth code from %T: %s", store, err)
61 match, field, expectation, result := compareAuthorizationCodes(authCode, retrieved)
63 t.Errorf("Expected `%v` in the `%s` field of auth code retrieved from %T, got `%v`", expectation, field, store, result)
65 err = store.deleteAuthorizationCode(authCode.Code)
67 t.Errorf("Error removing auth code from %T: %s", store, err)
69 retrieved, err = store.getAuthorizationCode(authCode.Code)
70 if err != ErrAuthorizationCodeNotFound {
71 t.Errorf("Expected ErrAuthorizationCodeNotFound from %T, got %+v and %+v", store, retrieved, err)
73 err = store.deleteAuthorizationCode(authCode.Code)
74 if err != ErrAuthorizationCodeNotFound {
75 t.Errorf("Expected ErrAuthorizationCodeNotFound from %T, got %+v", store, err)