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-14 02:12:07 +04:00
"errors"
2014-04-12 19:19:17 +04:00
"fmt"
2014-04-09 20:07:57 +04:00
"net/url"
"strings"
2014-08-10 04:25:02 +04:00
"time"
2014-04-02 06:39:04 +04:00
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-05-26 04:11:25 +04:00
"github.com/gogits/gogs/modules/setting"
2014-04-14 02:12:07 +04:00
"github.com/gogits/gogs/modules/social"
2014-04-02 06:39:04 +04:00
)
2014-04-09 20:07:57 +04:00
func extractPath ( next string ) string {
n , err := url . Parse ( next )
if err != nil {
return "/"
}
return n . Path
}
2014-07-26 08:24:27 +04:00
func SocialSignIn ( ctx * middleware . Context ) {
2014-05-26 04:11:25 +04:00
if setting . OauthService == nil {
2014-04-14 02:12:07 +04:00
ctx . Handle ( 404 , "social.SocialSignIn(oauth service not enabled)" , nil )
2014-04-09 20:07:57 +04:00
return
}
2014-04-14 02:12:07 +04:00
2014-04-12 19:19:17 +04:00
next := extractPath ( ctx . Query ( "next" ) )
2014-07-26 08:24:27 +04:00
name := ctx . Params ( ":name" )
2014-04-14 02:12:07 +04:00
connect , ok := social . SocialMap [ name ]
2014-04-12 19:19:17 +04:00
if ! ok {
2014-04-14 02:12:07 +04:00
ctx . Handle ( 404 , "social.SocialSignIn(social login not enabled)" , errors . New ( name ) )
2014-04-12 19:19:17 +04:00
return
2014-04-09 20:07:57 +04:00
}
2014-08-10 05:01:29 +04:00
appUrl := strings . TrimSuffix ( setting . AppUrl , "/" )
if name == "weibo" {
appUrl = strings . Replace ( appUrl , "localhost" , "127.0.0.1" , 1 )
}
2014-04-14 02:12:07 +04:00
2014-04-09 20:07:57 +04:00
code := ctx . Query ( "code" )
if code == "" {
// redirect to social login page
2014-08-10 05:01:29 +04:00
connect . SetRedirectUrl ( appUrl + ctx . Req . URL . Path )
2014-04-12 19:19:17 +04:00
ctx . Redirect ( connect . AuthCodeURL ( next ) )
2014-04-07 20:56:40 +04:00
return
}
2014-04-09 20:07:57 +04:00
// handle call back
2014-04-14 02:12:07 +04:00
tk , err := connect . Exchange ( code )
2014-04-09 20:07:57 +04:00
if err != nil {
2014-04-14 02:12:07 +04:00
ctx . Handle ( 500 , "social.SocialSignIn(Exchange)" , err )
2014-04-12 19:19:17 +04:00
return
2014-04-09 20:07:57 +04:00
}
next = extractPath ( ctx . Query ( "state" ) )
2014-04-14 02:12:07 +04:00
log . Trace ( "social.SocialSignIn(Got token)" )
2014-04-09 20:07:57 +04:00
2014-04-12 21:15:19 +04:00
ui , err := connect . UserInfo ( tk , ctx . Req . URL )
2014-04-12 19:19:17 +04:00
if err != nil {
2014-04-14 02:12:07 +04:00
ctx . Handle ( 500 , fmt . Sprintf ( "social.SocialSignIn(get info from %s)" , name ) , err )
2014-04-07 14:01:25 +04:00
return
}
2014-04-14 02:12:07 +04:00
log . Info ( "social.SocialSignIn(social login): %s" , ui )
2014-04-12 19:19:17 +04:00
oa , err := models . GetOauth2 ( ui . Identity )
2014-04-08 20:26:12 +04:00
switch err {
case nil :
2014-08-10 04:25:02 +04:00
ctx . Session . Set ( "uid" , oa . User . Id )
ctx . Session . Set ( "uname" , oa . User . Name )
2014-04-14 02:12:07 +04:00
case models . ErrOauth2RecordNotExist :
raw , _ := json . Marshal ( tk )
oa = & models . Oauth2 {
Uid : - 1 ,
Type : connect . Type ( ) ,
Identity : ui . Identity ,
Token : string ( raw ) ,
}
log . Trace ( "social.SocialSignIn(oa): %v" , oa )
2014-04-07 14:01:25 +04:00
if err = models . AddOauth2 ( oa ) ; err != nil {
2014-07-26 08:24:27 +04:00
log . Error ( 4 , "social.SocialSignIn(add oauth2): %v" , err ) // 501
2014-04-07 14:01:25 +04:00
return
}
2014-04-14 02:12:07 +04:00
case models . ErrOauth2NotAssociated :
2014-04-12 19:19:17 +04:00
next = "/user/sign_up"
2014-04-08 20:31:09 +04:00
default :
2014-04-14 02:12:07 +04:00
ctx . Handle ( 500 , "social.SocialSignIn(GetOauth2)" , err )
2014-04-08 20:31:09 +04:00
return
2014-04-07 14:01:25 +04:00
}
2014-04-14 02:12:07 +04:00
2014-08-10 04:25:02 +04:00
oa . Updated = time . Now ( )
if err = models . UpdateOauth2 ( oa ) ; err != nil {
log . Error ( 4 , "UpdateOauth2: %v" , err )
}
2014-04-08 20:26:12 +04:00
ctx . Session . Set ( "socialId" , oa . Id )
2014-04-12 19:19:17 +04:00
ctx . Session . Set ( "socialName" , ui . Name )
ctx . Session . Set ( "socialEmail" , ui . Email )
2014-04-14 02:12:07 +04:00
log . Trace ( "social.SocialSignIn(social ID): %v" , oa . Id )
2014-04-09 20:07:57 +04:00
ctx . Redirect ( next )
2014-04-02 06:39:04 +04:00
}