// UpdateUser does the following: // - Search for an existing user - session -> Profile -> email address // - Creates a User or appends the AuthID to the Requesting user's account // - Adds the admin role to the User if they are a GAE Admin. func (p *Profile) UpdateUser(w http.ResponseWriter, r *http.Request) (u *user.User, err error) { c := context.NewContext(r) if p.Key == nil { if p.ProviderName == "" && p.ID == "" { return nil, errors.New("auth: key not set") } p.SetKey(c) } var saveUser bool // flag indicating that the user needs to be saved. // Find the UserID // if the AuthProfile doesn't have a UserID look it up. And populate the // UserID from the saved profile. if p.UserID == "" { if p2, err := Get(c, p.Key.StringID()); err == nil { p.UserID = p2.UserID } } // look up the UserID in the session currentUserID, _ := user.CurrentUserID(r) if currentUserID != "" { if p.UserID == "" { p.UserID = currentUserID } else { // TODO: User merge } } // If we still don't have a UserID create a new user if p.UserID == "" { // Create User u = user.New() // Allocation an new ID if err = u.SetKey(c); err != nil { return nil, err } saveUser = true } else { if u, err = user.Get(c, p.UserID); err != nil { // if user is not found we have some type of syncing problem. c.Criticalf(`auth: userID: %v was saved to Profile / Session, but was not found in the datastore`, p.UserID) return nil, err } } // Add AuthID if err = u.AddAuthID(p.Key.StringID()); err == nil { saveUser = true } if p.Person.Email != "" { if _, err := u.AddEmail(c, p.Person.Email, 0); err == nil { saveUser = true } } // If current user is an admin in GAE add role to User if aeuser.IsAdmin(c) { // Save the roll to the session _ = user.CurrentUserSetRole(w, r, "admin", true) // Add the role to the user's roles. if err = u.AddRole("admin"); err == nil { saveUser = true } } if saveUser { if err = u.Put(c); err != nil { return nil, err } } p.UserID = u.Key.StringID() return u, nil }
func Test_CreateAndLogin(t *testing.T) { setup() defer teardown() c := context.NewContext(nil) up := profile.New("Example", "example.com") r, _ := http.NewRequest("GET", "http://localhost:8080/-/auth/example4", nil) w := httptest.NewRecorder() // Round 1: No User | No Profile // Confirm. q := datastore.NewQuery("User") if cnt, _ := q.Count(c); cnt != 0 { t.Errorf(`User cnt: %v, want 0`, cnt) } q = datastore.NewQuery("Profile") if cnt, _ := q.Count(c); cnt != 0 { t.Errorf(`Profile cnt: %v, want 0`, cnt) } u, err := user.Current(r) if err != user.ErrNoLoggedInUser { t.Errorf(`err: %v, want %v`, err, user.ErrNoLoggedInUser) } // Create. up.ID = "1" up.ProviderName = "Example" up.SetKey(c) u, err = CreateAndLogin(w, r, up) if err != nil { t.Errorf(`err: %v, want nil`, err) } if u.Key.StringID() != "1" { t.Errorf(`u.Key.StringID(): %v, want 1`, u.Key.StringID()) } if up.Key.StringID() != "example|1" { t.Errorf(`up.Key.StringID(): %v, want "example|1"`, up.Key.StringID()) } if up.UserID != u.Key.StringID() { t.Errorf(`up.UserID: %v, want %v`, up.UserID, u.Key.StringID()) } // Confirm Profile. rup, err := profile.Get(c, "example|1") if err != nil { t.Errorf(`err: %v, want nil`, err) } if rup.ID != "1" { t.Errorf(`rup.ID: %v, want "1"`, rup.ID) } if rup.Key.StringID() != "example|1" { t.Errorf(`rup.Key.StringID(): %v, want "example|1"`, rup.Key.StringID()) } if rup.UserID != u.Key.StringID() { t.Errorf(`rup.UserID: %v, want %v`, rup.UserID, u.Key.StringID()) } // Confirm User. ru, err := user.Get(c, "1") if err != nil { t.Fatalf(`err: %v, want nil`, err) } if ru.AuthIDs[0] != "example|1" { t.Errorf(`ru.AuthIDs[0]: %v, want "example|1"`, ru.AuthIDs[0]) } if ru.Key.StringID() != "1" { t.Errorf(`ru.Key.StringID(): %v, want 1`, ru.Key.StringID()) } q2 := datastore.NewQuery("User") q4 := datastore.NewQuery("AuthProfile") // Confirm Logged in User. u, err = user.Current(r) if err != nil { t.Errorf(`err: %v, want %v`, err, nil) } if u.Key.StringID() != "1" { t.Errorf(`u.Key.StringID(): %v, want 1`, u.Key.StringID()) } if len(u.AuthIDs) != 1 { t.Errorf(`len(u.AuthIDs): %v, want 1`, len(u.AuthIDs)) t.Errorf(`u.AuthIDs: %v`, u.AuthIDs) t.Errorf(`u: %v`, u) } // Round 2: Logged in User | Second Profile // Create. up = profile.New("AnotherExample", "anotherexample.com") up.ID = "2" up.SetKey(c) u, err = CreateAndLogin(w, r, up) if err != nil { t.Errorf(`err: %v, want nil`, err) } // Confirm Profile. rup, err = profile.Get(c, "anotherexample|2") if err != nil { t.Errorf(`err: %v, want nil`, err) } if rup.ID != "2" { t.Errorf(`rup.ID: %v, want "2"`, rup.ID) } if rup.Key.StringID() != "anotherexample|2" { t.Errorf(`rup.Key.StringID(): %v, want "anotherexample|2"`, rup.Key.StringID()) } if rup.UserID != u.Key.StringID() { t.Errorf(`rup.UserID: %v, want %v`, rup.UserID, u.Key.StringID()) } // Confirm Logged in User hasn't changed. u, err = user.Current(r) if err != nil { t.Errorf(`err: %v, want %v`, err, nil) } if u.Key.StringID() != "1" { t.Errorf(`u.Key.StringID(): %v, want 1`, u.Key.StringID()) } if len(u.AuthIDs) != 2 { t.Errorf(`len(u.AuthIDs): %v, want 2`, len(u.AuthIDs)) t.Errorf(`u.AuthIDs: %v`, u.AuthIDs) t.Errorf(`u: %v`, u) } if u.AuthIDs[0] != "example|1" { t.Errorf(`u.AuthIDs[0]: %v, want "example|1"`, u.AuthIDs[0]) } if u.AuthIDs[1] != "anotherexample|2" { t.Errorf(`u.AuthIDs[1]: %v, want "anotherexample|2"`, u.AuthIDs[1]) } // Confirm Counts q2 = datastore.NewQuery("User") if cnt, _ := q2.Count(c); cnt != 1 { t.Errorf(`User cnt: %v, want 1`, cnt) } q4 = datastore.NewQuery("AuthProfile") // Round 3: Logged out User | Existing Profile err = user.Logout(w, r) if err != nil { t.Errorf(`err: %v, want nil`, err) } // Confirm Logged out User. u, err = user.Current(r) if err != user.ErrNoLoggedInUser { t.Errorf(`err: %q, want %q`, err, user.ErrNoLoggedInUser) } // Login. up = profile.New("Example", "example.com") up.ID = "1" up.SetKey(c) u, err = CreateAndLogin(w, r, up) if err != nil { t.Errorf(`err: %v, want nil`, err) } // Confirm. q2 = datastore.NewQuery("User") if cnt, _ := q2.Count(c); cnt != 1 { t.Errorf(`User cnt: %v, want 1`, cnt) } q4 = datastore.NewQuery("AuthProfile") if cnt, _ := q4.Count(c); cnt != 2 { t.Errorf(`Profile cnt: %v, want 1`, cnt) } // Confirm Logged in User hasn't changed. u, err = user.Current(r) if err != nil { t.Errorf(`err: %v, want %v`, err, nil) } if u.Key.StringID() != "1" { t.Errorf(`u.Key.StringID(): %v, want "1"`, u.Key.StringID()) } if len(u.AuthIDs) != 2 { t.Errorf(`len(u.AuthIDs): %v, want 2`, len(u.AuthIDs)) t.Errorf(`u.AuthIDs: %s`, u.AuthIDs) t.Errorf(`u: %v`, u) } }