Skip to content

Commit

Permalink
support login via facebook
Browse files Browse the repository at this point in the history
  • Loading branch information
kylemcc committed Feb 22, 2015
1 parent 38a8072 commit 2f9cda5
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 4 deletions.
44 changes: 40 additions & 4 deletions session.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ type loginRequestT struct {
username string
password string
s *sessionT
authdata *AuthData
}

type sessionT struct {
Expand Down Expand Up @@ -54,6 +55,29 @@ func Login(username, password string, u interface{}) (Session, error) {
return s, nil
}

func LoginFacebook(authData *FacebookAuthData, u interface{}) (Session, error) {
var user interface{}

if u == nil {
user = &User{}
} else if err := validateUser(u); err != nil {
return nil, err
} else {
user = u
}

s := &sessionT{user: user}
if b, err := defaultClient.doRequest(&loginRequestT{authdata: &AuthData{Facebook: authData}}); err != nil {
return nil, err
} else if st, err := handleLoginResponse(b, s.user); err != nil {
return nil, err
} else {
s.sessionToken = st
}

return s, nil
}

// Log in as the user identified by the session token st
//
// Optionally provide a custom User type to use in place of parse.User. If user is
Expand Down Expand Up @@ -118,6 +142,10 @@ func (s *sessionT) Delete(v interface{}) error {
}

func (s *loginRequestT) method() string {
if s.authdata != nil {
return "POST"
}

return "GET"
}

Expand All @@ -127,19 +155,27 @@ func (s *loginRequestT) endpoint() (string, error) {
u.Host = parseHost
if s.s != nil {
u.Path = "/1/users/me"
} else if s.authdata != nil {
u.Path = "/1/users"
} else {
u.Path = "/1/login"
}

v := url.Values{}
v["username"] = []string{s.username}
v["password"] = []string{s.password}
u.RawQuery = v.Encode()
if s.username != "" && s.password != "" {
v := url.Values{}
v["username"] = []string{s.username}
v["password"] = []string{s.password}
u.RawQuery = v.Encode()
}

return u.String(), nil
}

func (s *loginRequestT) body() (string, error) {
if s.authdata != nil {
b, err := json.Marshal(map[string]interface{}{"authData": s.authdata})
return string(b), err
}
return "", nil
}

Expand Down
55 changes: 55 additions & 0 deletions types.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,58 @@ type Base struct {
Extra map[string]interface{} `parse:"-"`
}

type AnonymousAuthData struct {
Id string `json:"id"`
}

type TwitterAuthData struct {
Id string `json:"id"`
ScreenName string `json:"screen_name" parse:"screen_name"`
ConsumerKey string `json:"consumer_key" parse:"consumer_key"`
ConsumerSecret string `json:"consumer_secret" parse:"consumer_secret"`
AuthToken string `json:"auth_token" parse:"auth_token"`
AuthTokenSecret string `json:"auth_token_secret" parse:"auth_token_secret"`
}

type FacebookAuthData struct {
Id string
AccessToken string `parse:"access_token"`
ExpirationDate time.Time `parse:"expiration_date"`
}

func (a *FacebookAuthData) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
Id string `json:"id"`
AccessToken string `json:"access_token" parse:"access_token"`
ExpirationDate string `json:"expiration_date"`
}{
a.Id, a.AccessToken, a.ExpirationDate.Format("2006-01-02T15:04:05.000Z"),
})
}

func (a *FacebookAuthData) UnmarshalJSON(b []byte) (err error) {
data := struct {
Id string `json:"id"`
AccessToken string `json:"access_token" parse:"access_token"`
ExpirationDate string `json:"expiration_date"`
}{}

if err := json.Unmarshal(b, &data); err != nil {
return err
}

a.Id = data.Id
a.AccessToken = data.AccessToken
a.ExpirationDate, err = time.Parse("2006-01-02T15:04:05.000Z", data.ExpirationDate)
return err
}

type AuthData struct {
Twitter *TwitterAuthData `json:"twitter,omitempty"`
Facebook *FacebookAuthData `json:"facebook,omitempty"`
Anonymous *AnonymousAuthData `json:"anonymous,omitempty"`
}

// Represents the built-in Parse "User" class. Embed this type in a custom
// type containing any custom fields. When fetching user objects, any retrieved
// fields with no matching struct field will be stored in User.Extra (map[string]interface{})
Expand Down Expand Up @@ -553,6 +605,9 @@ func encodeForRequest(v interface{}) interface{} {
return v
case ACL, *ACL:
return v
case AuthData, *AuthData:
b, _ := json.Marshal(v)
return string(b)
default:
var cname string

Expand Down

0 comments on commit 2f9cda5

Please sign in to comment.