2014-04-02 06:39:04 +04:00
// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
2014-04-07 20:56:40 +04:00
2014-04-02 06:39:04 +04:00
package user
import (
"encoding/json"
2014-04-07 14:01:25 +04:00
"strconv"
2014-04-02 06:39:04 +04:00
2014-04-07 20:56:40 +04:00
"code.google.com/p/goauth2/oauth"
2014-04-07 14:01:25 +04:00
"github.com/gogits/gogs/models"
2014-04-02 06:39:04 +04:00
"github.com/gogits/gogs/modules/log"
2014-04-07 14:01:25 +04:00
"github.com/gogits/gogs/modules/middleware"
2014-04-07 20:56:40 +04:00
"github.com/gogits/gogs/modules/oauth2"
2014-04-02 06:39:04 +04:00
)
2014-04-07 14:01:25 +04:00
type SocialConnector interface {
Identity ( ) string
Type ( ) int
Name ( ) string
Email ( ) string
Token ( ) string
}
2014-04-02 06:39:04 +04:00
2014-04-07 14:01:25 +04:00
type SocialGithub struct {
data struct {
2014-04-02 06:39:04 +04:00
Id int ` json:"id" `
Name string ` json:"login" `
Email string ` json:"email" `
}
2014-04-07 14:01:25 +04:00
WebToken * oauth . Token
}
func ( s * SocialGithub ) Identity ( ) string {
return strconv . Itoa ( s . data . Id )
}
func ( s * SocialGithub ) Type ( ) int {
return models . OT_GITHUB
}
func ( s * SocialGithub ) Name ( ) string {
return s . data . Name
}
func ( s * SocialGithub ) Email ( ) string {
return s . data . Email
}
2014-04-02 06:39:04 +04:00
2014-04-07 14:01:25 +04:00
func ( s * SocialGithub ) Token ( ) string {
data , _ := json . Marshal ( s . WebToken )
return string ( data )
}
// Github API refer: https://developer.github.com/v3/users/
func ( s * SocialGithub ) Update ( ) error {
2014-04-02 06:39:04 +04:00
scope := "https://api.github.com/user"
2014-04-07 14:01:25 +04:00
transport := & oauth . Transport {
Token : s . WebToken ,
}
log . Debug ( "update github info" )
2014-04-02 06:39:04 +04:00
r , err := transport . Client ( ) . Get ( scope )
if err != nil {
2014-04-07 14:01:25 +04:00
return err
2014-04-02 06:39:04 +04:00
}
defer r . Body . Close ( )
2014-04-07 14:01:25 +04:00
return json . NewDecoder ( r . Body ) . Decode ( & s . data )
}
2014-04-02 06:39:04 +04:00
2014-04-07 14:01:25 +04:00
// github && google && ...
func SocialSignIn ( ctx * middleware . Context , tokens oauth2 . Tokens ) {
gh := & SocialGithub {
WebToken : & oauth . Token {
AccessToken : tokens . Access ( ) ,
RefreshToken : tokens . Refresh ( ) ,
Expiry : tokens . ExpiryTime ( ) ,
Extra : tokens . ExtraData ( ) ,
} ,
2014-04-02 06:39:04 +04:00
}
2014-04-07 20:56:40 +04:00
if len ( tokens . Access ( ) ) == 0 {
log . Error ( "empty access" )
return
}
2014-04-07 14:01:25 +04:00
var err error
if err = gh . Update ( ) ; err != nil {
// FIXME: handle error page
log . Error ( "connect with github error: %s" , err )
return
}
var soc SocialConnector = gh
log . Info ( "login: %s" , soc . Name ( ) )
2014-04-08 20:26:12 +04:00
oa , err := models . GetOauth2 ( soc . Identity ( ) )
switch err {
case nil :
ctx . Session . Set ( "userId" , oa . User . Id )
ctx . Session . Set ( "userName" , oa . User . Name )
case models . ErrOauth2RecordNotExists :
oa = & models . Oauth2 { }
oa . Uid = 0
2014-04-07 14:01:25 +04:00
oa . Type = soc . Type ( )
oa . Token = soc . Token ( )
oa . Identity = soc . Identity ( )
log . Info ( "oa: %v" , oa )
if err = models . AddOauth2 ( oa ) ; err != nil {
log . Error ( "add oauth2 %v" , err )
return
}
2014-04-08 20:26:12 +04:00
case models . ErrOauth2NotAssociatedWithUser :
// pass
2014-04-08 20:31:09 +04:00
default :
2014-04-08 23:27:35 +04:00
log . Error ( err . Error ( ) ) // FIXME: handle error page
2014-04-08 20:31:09 +04:00
return
2014-04-07 14:01:25 +04:00
}
2014-04-08 20:26:12 +04:00
ctx . Session . Set ( "socialId" , oa . Id )
log . Info ( "socialId: %v" , oa . Id )
2014-04-07 14:01:25 +04:00
ctx . Redirect ( "/" )
2014-04-02 06:39:04 +04:00
}