2023-05-24 12:16:03 +09:00
|
|
|
package core
|
|
|
|
|
|
|
|
|
|
import (
|
2023-06-28 16:10:28 +09:00
|
|
|
"context"
|
2024-04-22 17:58:53 +09:00
|
|
|
"crypto/md5"
|
|
|
|
|
"encoding/hex"
|
2023-05-24 12:16:03 +09:00
|
|
|
"encoding/json"
|
|
|
|
|
"errors"
|
|
|
|
|
"fmt"
|
|
|
|
|
"io"
|
|
|
|
|
"net/http"
|
2023-08-22 10:16:09 +09:00
|
|
|
"strconv"
|
2023-05-24 12:16:03 +09:00
|
|
|
"strings"
|
|
|
|
|
"time"
|
|
|
|
|
|
2023-06-29 21:21:49 +09:00
|
|
|
"repositories.action2quare.com/ayo/gocommon"
|
2023-05-24 15:31:01 +09:00
|
|
|
"repositories.action2quare.com/ayo/gocommon/logger"
|
2023-08-30 17:04:00 +09:00
|
|
|
"repositories.action2quare.com/ayo/gocommon/session"
|
2023-05-24 12:16:03 +09:00
|
|
|
|
|
|
|
|
"go.mongodb.org/mongo-driver/bson"
|
|
|
|
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
|
|
|
|
"go.mongodb.org/mongo-driver/mongo/options"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type blockinfo struct {
|
2023-11-29 17:36:25 +09:00
|
|
|
Start primitive.DateTime `bson:"start" json:"start"`
|
|
|
|
|
End primitive.DateTime `bson:"_ts" json:"_ts"`
|
|
|
|
|
Accid primitive.ObjectID `bson:"_id,omitempty" json:"_id,omitempty"`
|
|
|
|
|
Meta primitive.M `bson:"meta,omitempty" json:"meta,omitempty"`
|
2023-05-24 12:16:03 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type whitelistmember struct {
|
2023-08-22 11:10:59 +09:00
|
|
|
Id primitive.ObjectID `bson:"_id" json:"_id"`
|
2023-08-22 10:16:09 +09:00
|
|
|
Email string `bson:"email" json:"email"`
|
|
|
|
|
Platform string `bson:"platform" json:"platform"`
|
|
|
|
|
Desc string `bson:"desc" json:"desc"`
|
|
|
|
|
ExpiredAt primitive.DateTime `bson:"_ts,omitempty" json:"_ts,omitempty"`
|
2023-05-24 12:16:03 +09:00
|
|
|
}
|
|
|
|
|
|
2023-08-22 10:16:09 +09:00
|
|
|
func (wh *whitelistmember) Key() string {
|
|
|
|
|
if strings.HasPrefix(wh.Email, "*@") {
|
|
|
|
|
// 도메인 전체 허용
|
|
|
|
|
return wh.Email[2:]
|
|
|
|
|
}
|
|
|
|
|
return wh.Email
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (wh *whitelistmember) Expired() bool {
|
|
|
|
|
// 얘는 Expired가 있기만 하면 제거된 상태
|
|
|
|
|
return wh.ExpiredAt != 0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (bi *blockinfo) Key() primitive.ObjectID {
|
|
|
|
|
return bi.Accid
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (bi *blockinfo) Expired() bool {
|
2023-08-23 17:48:47 +09:00
|
|
|
return bi.End.Time().Unix() < time.Now().UTC().Unix()
|
2023-05-24 12:16:03 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type usertokeninfo struct {
|
|
|
|
|
platform string
|
|
|
|
|
userid string
|
|
|
|
|
token string //refreshtoken
|
|
|
|
|
secret string
|
|
|
|
|
brinfo string
|
|
|
|
|
accesstoken string // microsoft only
|
|
|
|
|
accesstoken_expire_time int64 // microsoft only
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-05 17:58:46 +09:00
|
|
|
type DivisionStateName string
|
2023-05-28 22:13:10 +09:00
|
|
|
|
2023-05-24 15:31:01 +09:00
|
|
|
const (
|
2023-06-05 17:58:46 +09:00
|
|
|
DivisionState_Closed = DivisionStateName("closed")
|
|
|
|
|
DivisionState_Maintenance = DivisionStateName("maintenance")
|
|
|
|
|
DivisionState_RestrictedOpen = DivisionStateName("restricted")
|
|
|
|
|
DivisionState_FullOpen = DivisionStateName("open")
|
2023-05-24 15:31:01 +09:00
|
|
|
)
|
|
|
|
|
|
2023-06-05 17:58:46 +09:00
|
|
|
type Maintenance struct {
|
2023-06-05 17:22:48 +09:00
|
|
|
Notice string `bson:"notice" json:"notice"`
|
2023-05-28 22:13:10 +09:00
|
|
|
StartTimeUTC int64 `bson:"start_unixtime_utc" json:"start_unixtime_utc"`
|
|
|
|
|
link string
|
2023-05-24 15:31:01 +09:00
|
|
|
}
|
|
|
|
|
|
2023-06-07 11:56:52 +09:00
|
|
|
type DivisionForUser struct {
|
|
|
|
|
Priority int `bson:"priority" json:"priority"`
|
|
|
|
|
State DivisionStateName `bson:"state" json:"state"`
|
2023-06-08 12:14:21 +09:00
|
|
|
Maintenance *Maintenance `bson:"maintenance,omitempty" json:"maintenance,omitempty"`
|
2023-06-07 11:56:52 +09:00
|
|
|
}
|
|
|
|
|
|
2023-06-05 18:01:09 +09:00
|
|
|
type Division struct {
|
2023-06-07 11:56:52 +09:00
|
|
|
DivisionForUser `bson:",inline" json:",inline"`
|
|
|
|
|
Url string `bson:"url" json:"url"`
|
2023-05-24 15:31:01 +09:00
|
|
|
}
|
|
|
|
|
|
2023-05-24 12:16:03 +09:00
|
|
|
type serviceDescription struct {
|
2024-03-29 09:06:38 +09:00
|
|
|
Id primitive.ObjectID `bson:"_id" json:"_id"`
|
|
|
|
|
Divisions map[string]*Division `bson:"divisions" json:"divisions"`
|
|
|
|
|
ServerApiTokens []primitive.ObjectID `bson:"api_tokens" json:"api_tokens"`
|
|
|
|
|
MaximumNumLinkAccount int64
|
|
|
|
|
VersionSplits map[string]string `bson:"version_splits" json:"version_splits"`
|
2023-05-24 12:16:03 +09:00
|
|
|
|
2023-08-30 17:04:00 +09:00
|
|
|
sessionProvider session.Provider
|
2023-10-05 11:11:20 +09:00
|
|
|
wl *memberContainerPtr[string, *whitelistmember]
|
|
|
|
|
bl *memberContainerPtr[primitive.ObjectID, *blockinfo]
|
2023-08-30 17:04:00 +09:00
|
|
|
mongoClient gocommon.MongoClient
|
|
|
|
|
sessionTTL time.Duration
|
2023-06-28 16:10:28 +09:00
|
|
|
|
2023-05-24 12:16:03 +09:00
|
|
|
getUserBrowserInfo func(r *http.Request) (string, error)
|
|
|
|
|
getUserTokenWithCheck func(platform string, userid string, brinfo string) (usertokeninfo, error)
|
|
|
|
|
updateUserinfo func(info usertokeninfo) (bool, string, string)
|
2023-05-24 15:31:01 +09:00
|
|
|
getProviderInfo func(platform string, uid string) (string, string, error)
|
2023-05-24 12:16:03 +09:00
|
|
|
|
2023-09-04 11:15:05 +09:00
|
|
|
divisionsSerialized []byte
|
|
|
|
|
serviceSerialized []byte
|
|
|
|
|
divisionsSplits map[string][]byte
|
2024-04-22 17:58:53 +09:00
|
|
|
mustUseChecksum bool
|
2023-05-24 12:16:03 +09:00
|
|
|
}
|
|
|
|
|
|
2023-06-19 21:19:45 +09:00
|
|
|
func (sh *serviceDescription) isValidToken(apiToken primitive.ObjectID) bool {
|
2023-06-23 17:58:41 +09:00
|
|
|
if *devflag {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-19 21:19:45 +09:00
|
|
|
if apiToken.IsZero() {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, test := range sh.ServerApiTokens {
|
|
|
|
|
if test == apiToken {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-24 12:16:03 +09:00
|
|
|
func (sh *serviceDescription) readProfile(authtype string, id string, binfo string) (email string, err error) {
|
|
|
|
|
defer func() {
|
|
|
|
|
s := recover()
|
|
|
|
|
if s != nil {
|
|
|
|
|
logger.Error("readProfile failed :", authtype, id, s)
|
|
|
|
|
if errt, ok := s.(error); ok {
|
|
|
|
|
err = errt
|
|
|
|
|
} else {
|
|
|
|
|
err = errors.New(fmt.Sprint(s))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
userinfo, err := sh.getUserTokenWithCheck(authtype, id, binfo)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
2023-10-18 15:28:14 +09:00
|
|
|
|
2023-08-18 13:56:34 +09:00
|
|
|
if len(userinfo.token) == 0 {
|
2023-05-24 12:16:03 +09:00
|
|
|
return "", errors.New("refreshtoken token not found")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-- 토큰으로 모두 확인이 끝났으면 갱신한다.
|
|
|
|
|
ok, _, email := sh.updateUserinfo(userinfo)
|
|
|
|
|
|
|
|
|
|
if !ok {
|
|
|
|
|
return "", errors.New("updateUserinfo failed")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return email, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (sh *serviceDescription) prepare(mg *Maingate) error {
|
2023-05-28 22:13:10 +09:00
|
|
|
divs := sh.Divisions
|
2023-06-26 17:34:30 +09:00
|
|
|
|
2023-06-07 11:56:52 +09:00
|
|
|
divsForUsers := make(map[string]*DivisionForUser)
|
2023-09-04 11:15:05 +09:00
|
|
|
defaultDivNames := make(map[string]bool)
|
2023-05-28 22:13:10 +09:00
|
|
|
for dn, div := range divs {
|
2023-09-05 17:14:56 +09:00
|
|
|
if div.State != DivisionState_Closed {
|
|
|
|
|
defaultDivNames[dn] = true
|
2023-05-28 22:13:10 +09:00
|
|
|
}
|
|
|
|
|
|
2023-06-07 11:56:52 +09:00
|
|
|
divsForUsers[dn] = &div.DivisionForUser
|
2023-05-28 22:13:10 +09:00
|
|
|
if len(div.State) == 0 {
|
|
|
|
|
div.State = DivisionState_FullOpen
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if div.State != DivisionState_FullOpen {
|
|
|
|
|
if div.Maintenance == nil {
|
2023-06-05 17:58:46 +09:00
|
|
|
div.Maintenance = &Maintenance{}
|
2023-05-28 22:13:10 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if len(div.Maintenance.link) == 0 {
|
|
|
|
|
if len(div.Maintenance.Notice) == 0 {
|
|
|
|
|
div.Maintenance.link = "https://www.action2quare.com"
|
|
|
|
|
} else if strings.HasPrefix(div.Maintenance.Notice, "http") {
|
|
|
|
|
div.Maintenance.link = div.Maintenance.Notice
|
|
|
|
|
} else {
|
2023-06-29 21:21:49 +09:00
|
|
|
var fd FileDocumentDesc
|
2023-06-29 21:31:51 +09:00
|
|
|
if err := mg.mongoClient.FindOneAs(CollectionFile, bson.M{
|
2023-06-29 21:21:49 +09:00
|
|
|
"key": div.Maintenance.Notice,
|
|
|
|
|
}, &fd, options.FindOne().SetProjection(bson.M{"link": 1})); err != nil {
|
|
|
|
|
logger.Println(err)
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
div.Maintenance.link = fd.Link
|
|
|
|
|
logger.Println("div.Maintenance.link :", fd.Link)
|
2023-05-28 22:13:10 +09:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
div.Maintenance = nil
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-16 21:44:19 +09:00
|
|
|
sh.divisionsSerialized, _ = json.Marshal(divs)
|
|
|
|
|
sh.divisionsSplits = make(map[string][]byte)
|
|
|
|
|
for ver, divnamesT := range sh.VersionSplits {
|
2023-09-05 17:14:56 +09:00
|
|
|
if ver == "default" {
|
|
|
|
|
continue
|
|
|
|
|
}
|
2023-08-16 21:44:19 +09:00
|
|
|
divnames := strings.Split(divnamesT, ",")
|
|
|
|
|
split := make(map[string]*DivisionForUser)
|
|
|
|
|
for _, divname := range divnames {
|
|
|
|
|
split[divname] = divsForUsers[divname]
|
2023-09-04 11:15:05 +09:00
|
|
|
|
|
|
|
|
// 스플릿 된 버전은 default에서 제거해야 한다.
|
|
|
|
|
delete(defaultDivNames, divname)
|
2023-08-16 21:44:19 +09:00
|
|
|
}
|
|
|
|
|
splitMarshaled, _ := json.Marshal(split)
|
|
|
|
|
sh.divisionsSplits[ver] = splitMarshaled
|
|
|
|
|
}
|
2023-06-07 11:56:52 +09:00
|
|
|
|
2023-09-04 11:15:05 +09:00
|
|
|
defaultsDivs := make(map[string]*DivisionForUser)
|
|
|
|
|
for divname := range defaultDivNames {
|
|
|
|
|
defaultsDivs[divname] = divsForUsers[divname]
|
|
|
|
|
}
|
|
|
|
|
defaultMarshaled, _ := json.Marshal(defaultsDivs)
|
|
|
|
|
sh.divisionsSplits["default"] = defaultMarshaled
|
|
|
|
|
|
2023-12-06 16:35:55 +09:00
|
|
|
sh.MaximumNumLinkAccount = config.MaximumNumLinkAccount
|
2023-05-24 12:16:03 +09:00
|
|
|
sh.mongoClient = mg.mongoClient
|
2023-08-30 17:04:00 +09:00
|
|
|
sh.sessionProvider = mg.sessionProvider
|
2023-12-06 16:35:55 +09:00
|
|
|
sh.sessionTTL = time.Duration(config.SessionTTL * int64(time.Second))
|
2023-05-24 12:16:03 +09:00
|
|
|
sh.getUserBrowserInfo = mg.GetUserBrowserInfo
|
|
|
|
|
sh.getUserTokenWithCheck = mg.getUserTokenWithCheck
|
|
|
|
|
sh.updateUserinfo = mg.updateUserinfo
|
|
|
|
|
sh.getProviderInfo = mg.getProviderInfo
|
2023-06-20 11:29:17 +09:00
|
|
|
|
2024-02-02 12:45:42 +09:00
|
|
|
if globalApiToken, err := primitive.ObjectIDFromHex(config.GlobalMaingateToken); err == nil {
|
|
|
|
|
if !globalApiToken.IsZero() {
|
2024-02-04 15:23:33 +09:00
|
|
|
f := func() bool {
|
|
|
|
|
for _, t := range sh.ServerApiTokens {
|
|
|
|
|
if t == globalApiToken {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false
|
|
|
|
|
}()
|
|
|
|
|
if !f {
|
|
|
|
|
sh.ServerApiTokens = append(sh.ServerApiTokens, globalApiToken)
|
|
|
|
|
}
|
2024-02-02 12:45:42 +09:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-05 11:11:20 +09:00
|
|
|
sh.wl = &mg.wl
|
|
|
|
|
sh.bl = &mg.bl
|
2023-08-22 11:10:59 +09:00
|
|
|
sh.serviceSerialized, _ = json.Marshal(sh)
|
2023-05-24 12:16:03 +09:00
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (sh *serviceDescription) link(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
defer func() {
|
|
|
|
|
s := recover()
|
|
|
|
|
if s != nil {
|
|
|
|
|
logger.Error(s)
|
|
|
|
|
}
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
if r.Method != "GET" {
|
|
|
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
queryvals := r.URL.Query()
|
|
|
|
|
//oldToken := queryvals.Get("otoken")
|
|
|
|
|
oldType := queryvals.Get("otype")
|
|
|
|
|
oldId := queryvals.Get("oid")
|
|
|
|
|
sk := queryvals.Get("sk")
|
|
|
|
|
//newToken := queryvals.Get("ntoken")
|
|
|
|
|
newType := queryvals.Get("ntype")
|
|
|
|
|
newId := queryvals.Get("nid")
|
|
|
|
|
|
2023-08-30 17:04:00 +09:00
|
|
|
oldAuth, err := sh.sessionProvider.Query(sk)
|
|
|
|
|
if err != nil {
|
|
|
|
|
logger.Println("sessionProvider.Query return err :", err)
|
|
|
|
|
w.WriteHeader(http.StatusInternalServerError)
|
2023-05-24 12:16:03 +09:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-27 15:18:09 +09:00
|
|
|
bfinfo, err := sh.getUserBrowserInfo(r)
|
|
|
|
|
if err != nil {
|
|
|
|
|
logger.Error("getUserBrowserInfo failed :", err)
|
|
|
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
guestlink := (oldAuth.Platform == "guest")
|
|
|
|
|
if !guestlink {
|
|
|
|
|
_, err = sh.readProfile(oldType, oldId, bfinfo)
|
|
|
|
|
if err != nil {
|
|
|
|
|
logger.Error("readProfile(old) failed :", err)
|
|
|
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
logger.Println("from guest acc to real acc link : ", oldId, bfinfo, newType, newId, bfinfo)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
oldType, oldId, err = sh.getProviderInfo(oldType, oldId)
|
|
|
|
|
if err != nil {
|
|
|
|
|
logger.Error("getProviderInfo failed :", err)
|
|
|
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-24 12:16:03 +09:00
|
|
|
// fmt.Println("=================")
|
|
|
|
|
// fmt.Println(oldType)
|
|
|
|
|
// fmt.Println(oldId)
|
|
|
|
|
// fmt.Println("=================")
|
|
|
|
|
// fmt.Println(newType)
|
|
|
|
|
// fmt.Println(newId)
|
|
|
|
|
// fmt.Println("=================")
|
|
|
|
|
// fmt.Println(oldAuth.Platform)
|
|
|
|
|
// fmt.Println(oldAuth.Uid)
|
|
|
|
|
// fmt.Println("=================")
|
|
|
|
|
|
|
|
|
|
//if oldAuth.Token != oldToken || oldAuth.Uid != oldId || oldAuth.Platform != oldType {
|
|
|
|
|
if oldAuth.Uid != oldId || oldAuth.Platform != oldType {
|
2023-09-04 14:37:58 +09:00
|
|
|
logger.Println("link failed. session key is not correct :", oldAuth, queryvals)
|
2023-05-24 12:16:03 +09:00
|
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
email, err := sh.readProfile(newType, newId, bfinfo)
|
|
|
|
|
if err != nil {
|
|
|
|
|
logger.Error("readProfile(new) failed :", err)
|
|
|
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// if len(email) == 0 {
|
|
|
|
|
// logger.Println("link failed. email is missing :", r.URL.Query())
|
|
|
|
|
// w.WriteHeader(http.StatusBadRequest)
|
|
|
|
|
// return
|
|
|
|
|
// }
|
|
|
|
|
|
2023-05-24 15:31:01 +09:00
|
|
|
newType, newId, err = sh.getProviderInfo(newType, newId)
|
2023-05-24 12:16:03 +09:00
|
|
|
if err != nil {
|
|
|
|
|
logger.Error("getProviderInfo failed :", err)
|
|
|
|
|
w.WriteHeader(http.StatusBadRequest)
|
2024-06-27 15:18:09 +09:00
|
|
|
return
|
2023-05-24 12:16:03 +09:00
|
|
|
}
|
|
|
|
|
|
2024-07-03 14:44:53 +09:00
|
|
|
found, err := sh.mongoClient.FindOne(CollectionLink, bson.M{"platform": newType, "uid": newId}, options.FindOne())
|
|
|
|
|
if err != nil {
|
|
|
|
|
logger.Error("link failed. FindOne err:", err)
|
|
|
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if found != nil {
|
|
|
|
|
logger.Println("link failed. already have service account: ", r.URL.Query())
|
|
|
|
|
w.Write([]byte(`{"alreadylink":true}`))
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-24 12:16:03 +09:00
|
|
|
createtime := primitive.NewDateTimeFromTime(time.Now().UTC())
|
|
|
|
|
link, err := sh.mongoClient.FindOneAndUpdate(CollectionLink, bson.M{
|
|
|
|
|
"platform": newType,
|
|
|
|
|
"uid": newId,
|
|
|
|
|
}, bson.M{
|
|
|
|
|
"$setOnInsert": bson.M{
|
|
|
|
|
"create": createtime,
|
|
|
|
|
"email": email,
|
|
|
|
|
},
|
|
|
|
|
}, options.FindOneAndUpdate().SetReturnDocument(options.After).SetUpsert(true).SetProjection(bson.M{"_id": 1}))
|
|
|
|
|
if err != nil {
|
|
|
|
|
logger.Error("link failed. FindOneAndUpdate link err:", err)
|
|
|
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-20 12:02:29 +09:00
|
|
|
_, newid, err := sh.mongoClient.Update(CollectionAccount, bson.M{
|
2023-05-24 12:16:03 +09:00
|
|
|
"_id": link["_id"].(primitive.ObjectID),
|
|
|
|
|
}, bson.M{
|
|
|
|
|
"$setOnInsert": bson.M{
|
2023-08-30 17:04:00 +09:00
|
|
|
"accid": oldAuth.Account,
|
2023-05-24 12:16:03 +09:00
|
|
|
"create": createtime,
|
|
|
|
|
},
|
|
|
|
|
}, options.Update().SetUpsert(true))
|
|
|
|
|
if err != nil {
|
|
|
|
|
logger.Error("link failed. Update ServiceName err :", err)
|
|
|
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// newid가 있어야 한다. 그래야 기존 서비스 계정이 없는 상태이다.
|
|
|
|
|
if newid == nil {
|
|
|
|
|
// 이미 계정이 있네?
|
|
|
|
|
logger.Println("link failed. already have service account :", r.URL.Query())
|
|
|
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-27 15:18:09 +09:00
|
|
|
if guestlink {
|
|
|
|
|
//기존 게스트 링크 삭제
|
|
|
|
|
link, err = sh.mongoClient.FindOneAndDelete(CollectionLink, bson.M{
|
|
|
|
|
"platform": oldType,
|
|
|
|
|
"uid": oldId,
|
|
|
|
|
}, options.FindOneAndDelete().SetProjection(bson.M{"_id": 1}))
|
|
|
|
|
|
|
|
|
|
if err == nil {
|
|
|
|
|
sh.mongoClient.Delete(CollectionAccount, bson.M{
|
|
|
|
|
"_id": link["_id"].(primitive.ObjectID),
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-24 12:16:03 +09:00
|
|
|
logger.Println("link success :", r.URL.Query())
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-28 16:10:28 +09:00
|
|
|
// == link된 계정을 해제 한다. but, 최소 1개 계정은 연결되어 있어야 한다.
|
|
|
|
|
func (sh *serviceDescription) unlink(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
defer func() {
|
|
|
|
|
s := recover()
|
|
|
|
|
if s != nil {
|
|
|
|
|
logger.Error(s)
|
|
|
|
|
}
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
if r.Method != "GET" {
|
|
|
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
queryvals := r.URL.Query()
|
|
|
|
|
sType := queryvals.Get("stype")
|
|
|
|
|
sId := queryvals.Get("sid")
|
|
|
|
|
sk := queryvals.Get("sk")
|
|
|
|
|
|
2023-08-30 17:04:00 +09:00
|
|
|
authInfo, err := sh.sessionProvider.Query(sk)
|
|
|
|
|
if err != nil {
|
|
|
|
|
logger.Println("sessionProvider.Query return err :", err)
|
|
|
|
|
w.WriteHeader(http.StatusInternalServerError)
|
2023-06-28 16:10:28 +09:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// fmt.Println("=================")
|
|
|
|
|
// fmt.Println(sType)
|
|
|
|
|
// fmt.Println(sId)
|
|
|
|
|
// fmt.Println("=================")
|
|
|
|
|
// fmt.Println(authInfo.Platform)
|
|
|
|
|
// fmt.Println(authInfo.Uid)
|
|
|
|
|
// fmt.Println("=================")
|
|
|
|
|
|
|
|
|
|
if authInfo.Uid != sId || authInfo.Platform != sType {
|
2023-09-04 14:37:58 +09:00
|
|
|
logger.Println("unlink failed. session key is not correct :", authInfo, queryvals)
|
2023-06-28 16:10:28 +09:00
|
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
numRecord, err := sh.mongoClient.Collection(CollectionAccount).CountDocuments(context.Background(), bson.M{
|
2023-08-30 17:04:00 +09:00
|
|
|
"accid": authInfo.Account,
|
2023-06-28 16:10:28 +09:00
|
|
|
}, options.Count().SetLimit(2))
|
|
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
logger.Error("unlink failed, fail to count accounts :", err)
|
|
|
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if numRecord <= 1 {
|
|
|
|
|
logger.Println("unlink failed. At least one link must be maintained. :", r.URL.Query())
|
|
|
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sType, sId, err = sh.getProviderInfo(sType, sId)
|
|
|
|
|
if err != nil {
|
|
|
|
|
logger.Error("getProviderInfo failed :", err)
|
|
|
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
link, err := sh.mongoClient.FindOne(CollectionLink, bson.M{
|
|
|
|
|
"platform": sType,
|
|
|
|
|
"uid": sId,
|
|
|
|
|
}, options.FindOne().SetProjection(bson.M{"_id": 1}))
|
|
|
|
|
if err != nil {
|
|
|
|
|
logger.Error("link failed. FindOneAndUpdate link err:", err)
|
|
|
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
newid, err := sh.mongoClient.FindOneAndDelete(CollectionAccount, bson.M{
|
|
|
|
|
"_id": link["_id"].(primitive.ObjectID),
|
|
|
|
|
}, options.FindOneAndDelete().SetProjection(bson.M{"_id": 1}))
|
|
|
|
|
if err != nil {
|
|
|
|
|
logger.Error("unlink failed. Delete ServiceName err :", err)
|
|
|
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// newid가 있어야 한다. 그래야 기존 서비스 계정이 없는 상태이다.
|
|
|
|
|
if newid == nil {
|
|
|
|
|
// 이미 계정이 있네?
|
|
|
|
|
logger.Println("unlink failed. service account not found:", r.URL.Query())
|
|
|
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
logger.Println("unlink success :", r.URL.Query())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// == 연결된 계정 정보(숫자) 전달하는 API
|
|
|
|
|
func (sh *serviceDescription) linkinfo(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
defer func() {
|
|
|
|
|
s := recover()
|
|
|
|
|
if s != nil {
|
|
|
|
|
logger.Error(s)
|
|
|
|
|
}
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
if r.Method != "GET" {
|
|
|
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
queryvals := r.URL.Query()
|
|
|
|
|
sType := queryvals.Get("stype")
|
|
|
|
|
sId := queryvals.Get("sid")
|
|
|
|
|
sk := queryvals.Get("sk")
|
|
|
|
|
|
2023-08-30 17:04:00 +09:00
|
|
|
authInfo, err := sh.sessionProvider.Query(sk)
|
|
|
|
|
if err != nil {
|
|
|
|
|
logger.Println("sessionProvider.Query return err :", err)
|
|
|
|
|
w.WriteHeader(http.StatusInternalServerError)
|
2023-06-28 16:10:28 +09:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// fmt.Println("=================")
|
|
|
|
|
// fmt.Println(sType)
|
|
|
|
|
// fmt.Println(sId)
|
|
|
|
|
// fmt.Println("=================")
|
|
|
|
|
// fmt.Println(authInfo.Platform)
|
|
|
|
|
// fmt.Println(authInfo.Uid)
|
|
|
|
|
// fmt.Println("=================")
|
|
|
|
|
|
|
|
|
|
//if oldAuth.Token != oldToken || oldAuth.Uid != oldId || oldAuth.Platform != oldType {
|
|
|
|
|
if authInfo.Uid != sId || authInfo.Platform != sType {
|
2023-09-04 14:37:58 +09:00
|
|
|
logger.Println("linkinfo failed. session key is not correct :", authInfo, queryvals)
|
2023-06-28 16:10:28 +09:00
|
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
numRecord, err := sh.mongoClient.Collection(CollectionAccount).CountDocuments(context.Background(), bson.M{
|
2023-08-30 17:04:00 +09:00
|
|
|
"accid": authInfo.Account,
|
2023-06-28 16:10:28 +09:00
|
|
|
}, options.Count().SetLimit(sh.MaximumNumLinkAccount))
|
|
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
logger.Error("linkinfo failed. CountDocuments err :", err)
|
|
|
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
logger.Println("linkinfo :", numRecord)
|
|
|
|
|
w.Write([]byte(fmt.Sprintf(`{"num_linked_account":"%d"}`, numRecord)))
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-10 07:37:06 +09:00
|
|
|
// == 계정 이메일 조회
|
|
|
|
|
func (sh *serviceDescription) emailinfo(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
defer func() {
|
|
|
|
|
s := recover()
|
|
|
|
|
if s != nil {
|
|
|
|
|
logger.Error(s)
|
|
|
|
|
}
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
if r.Method != "GET" {
|
|
|
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
queryvals := r.URL.Query()
|
|
|
|
|
sk := queryvals.Get("sk")
|
|
|
|
|
|
|
|
|
|
authInfo, err := sh.sessionProvider.Query(sk)
|
|
|
|
|
if err != nil {
|
|
|
|
|
logger.Println("sessionProvider.Query return err :", err)
|
|
|
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
email := authInfo.Email
|
|
|
|
|
|
|
|
|
|
if strings.HasPrefix(email, "__dummy_") && strings.HasSuffix(email, "temp__") {
|
|
|
|
|
email = ""
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if strings.HasSuffix(email, "@noauth.flag") || strings.HasSuffix(email, "@guest.flag") {
|
|
|
|
|
email = ""
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// fmt.Println("=================")
|
|
|
|
|
// fmt.Println(email)
|
|
|
|
|
// fmt.Println("=================")
|
|
|
|
|
//logger.Println("Email :", email)
|
|
|
|
|
|
|
|
|
|
w.Write([]byte(fmt.Sprintf(`{"email":"%s"}`, email)))
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-25 22:08:22 +09:00
|
|
|
func (sh *serviceDescription) authorize_dev(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
if r.Method == "DELETE" {
|
|
|
|
|
sk := r.Header.Get("AS-X-SESSION")
|
|
|
|
|
if authinfo, err := sh.sessionProvider.Query(sk); err == nil {
|
2023-12-28 16:55:38 +09:00
|
|
|
bt := r.Header.Get("AS-X-BLOCK")
|
|
|
|
|
if len(bt) > 0 {
|
|
|
|
|
dur, _ := strconv.ParseInt(bt, 10, 0)
|
|
|
|
|
sh.bl.add(&blockinfo{
|
|
|
|
|
Start: primitive.NewDateTimeFromTime(time.Now().UTC()),
|
|
|
|
|
End: primitive.NewDateTimeFromTime(time.Now().UTC().Add(time.Second * time.Duration(dur))),
|
|
|
|
|
Accid: authinfo.Account,
|
|
|
|
|
})
|
|
|
|
|
}
|
2024-04-23 11:24:19 +09:00
|
|
|
sh.sessionProvider.RevokeAll(authinfo.Account)
|
2023-12-25 22:08:22 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return
|
|
|
|
|
}
|
2023-12-28 16:55:38 +09:00
|
|
|
|
2023-12-25 22:08:22 +09:00
|
|
|
sh.authorize(w, r)
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-24 12:16:03 +09:00
|
|
|
func (sh *serviceDescription) authorize(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
defer func() {
|
|
|
|
|
s := recover()
|
|
|
|
|
if s != nil {
|
|
|
|
|
logger.Error(s)
|
|
|
|
|
}
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
if r.Method != "GET" {
|
|
|
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
queryvals := r.URL.Query()
|
2024-07-10 14:54:13 +09:00
|
|
|
reqauthtype := queryvals.Get("type")
|
2023-05-24 12:16:03 +09:00
|
|
|
uid := queryvals.Get("id")
|
2024-04-22 17:58:53 +09:00
|
|
|
sk := queryvals.Get("sk")
|
|
|
|
|
|
|
|
|
|
checksum := r.Header.Get("AS-X-CHECKSUM")
|
|
|
|
|
if len(checksum) > 0 || sh.mustUseChecksum {
|
|
|
|
|
nonce := queryvals.Get("nonce")
|
|
|
|
|
cookie := r.Header.Get("Cookie")
|
|
|
|
|
|
|
|
|
|
h := md5.New()
|
|
|
|
|
h.Write([]byte(cookie + nonce + sk))
|
|
|
|
|
|
|
|
|
|
if checksum != hex.EncodeToString(h.Sum(nil)) {
|
|
|
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if len(sk) > 0 {
|
2023-09-04 12:17:34 +09:00
|
|
|
success, err := sh.sessionProvider.Touch(sk)
|
|
|
|
|
if err != nil {
|
|
|
|
|
logger.Error("authorize failed. sessionProvider.Touch err:", err)
|
|
|
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// !success일 때 빈 body를 보내면 클라이언트는 로그아웃 된다.
|
|
|
|
|
if success {
|
2023-09-19 18:50:45 +09:00
|
|
|
json.NewEncoder(w).Encode(map[string]any{
|
2023-09-04 12:17:34 +09:00
|
|
|
"sk": sk,
|
|
|
|
|
"expirein": sh.sessionTTL.Seconds(),
|
2023-09-19 18:50:45 +09:00
|
|
|
})
|
|
|
|
|
} else {
|
2023-12-28 16:55:38 +09:00
|
|
|
w.WriteHeader(http.StatusUnauthorized)
|
|
|
|
|
}
|
2023-09-04 12:17:34 +09:00
|
|
|
return
|
|
|
|
|
}
|
2023-08-31 17:24:21 +09:00
|
|
|
|
2023-06-20 15:50:18 +09:00
|
|
|
var email string
|
2024-07-10 14:54:13 +09:00
|
|
|
if !*noauth && (*authtype == "on" || *authtype == "both") {
|
|
|
|
|
if len(reqauthtype) > 0 {
|
2023-08-09 17:39:16 +09:00
|
|
|
//email, err := sh.readProfile(authtype, uid, accesstoken)
|
|
|
|
|
bfinfo, err := sh.getUserBrowserInfo(r)
|
|
|
|
|
if err != nil {
|
|
|
|
|
logger.Error("getUserBrowserInfo failed :", err)
|
|
|
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
|
|
|
return
|
|
|
|
|
}
|
2023-05-24 12:16:03 +09:00
|
|
|
|
2024-07-10 14:54:13 +09:00
|
|
|
email, err = sh.readProfile(reqauthtype, uid, bfinfo)
|
2023-08-09 17:39:16 +09:00
|
|
|
if err != nil {
|
|
|
|
|
logger.Error("readProfile failed :", err)
|
|
|
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
|
|
|
return
|
|
|
|
|
}
|
2023-05-24 12:16:03 +09:00
|
|
|
|
2024-07-10 14:54:13 +09:00
|
|
|
newType, newId, err := sh.getProviderInfo(reqauthtype, uid)
|
2023-08-09 17:39:16 +09:00
|
|
|
if err != nil {
|
|
|
|
|
logger.Error("getProviderInfo failed :", err)
|
|
|
|
|
w.WriteHeader(http.StatusBadRequest)
|
2023-09-19 18:50:45 +09:00
|
|
|
return
|
2023-08-09 17:39:16 +09:00
|
|
|
}
|
2023-05-24 12:16:03 +09:00
|
|
|
|
2024-07-10 14:54:13 +09:00
|
|
|
if reqauthtype != newType || uid != newId {
|
|
|
|
|
reqauthtype = newType
|
2023-08-09 17:39:16 +09:00
|
|
|
uid = newId
|
|
|
|
|
}
|
2024-07-10 14:54:13 +09:00
|
|
|
} else if *authtype == "both" {
|
2023-08-09 17:39:16 +09:00
|
|
|
email = fmt.Sprintf("%s@guest.flag", uid)
|
2023-10-20 11:27:41 +09:00
|
|
|
} else {
|
|
|
|
|
// authtype이 없으면 입장 불가
|
|
|
|
|
logger.Error("authorize failed. 'type' query parameter is missing")
|
|
|
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
|
|
|
return
|
2023-06-20 15:50:18 +09:00
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
email = fmt.Sprintf("%s@noauth.flag", uid)
|
2023-05-24 12:16:03 +09:00
|
|
|
}
|
|
|
|
|
|
2023-08-31 17:24:21 +09:00
|
|
|
// platform + id -> account id
|
|
|
|
|
createtime := primitive.NewDateTimeFromTime(time.Now().UTC())
|
|
|
|
|
link, err := sh.mongoClient.FindOneAndUpdate(CollectionLink, bson.M{
|
|
|
|
|
"platform": authtype,
|
|
|
|
|
"uid": uid,
|
|
|
|
|
}, bson.M{
|
|
|
|
|
"$setOnInsert": bson.M{
|
|
|
|
|
"create": createtime,
|
|
|
|
|
"email": email,
|
|
|
|
|
},
|
2024-07-15 12:37:52 +09:00
|
|
|
}, options.FindOneAndUpdate().SetReturnDocument(options.After).SetUpsert(true).SetProjection(bson.M{"_id": 1, "_ts": 1}))
|
2023-08-31 17:24:21 +09:00
|
|
|
if err != nil {
|
|
|
|
|
logger.Error("authorize failed :", err)
|
|
|
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
|
|
|
return
|
|
|
|
|
}
|
2023-05-24 12:16:03 +09:00
|
|
|
|
2023-08-31 17:24:21 +09:00
|
|
|
linkid := link["_id"].(primitive.ObjectID)
|
|
|
|
|
newaccid := primitive.NewObjectID()
|
|
|
|
|
account, err := sh.mongoClient.FindOneAndUpdate(CollectionAccount, bson.M{
|
|
|
|
|
"_id": linkid,
|
|
|
|
|
}, bson.M{
|
|
|
|
|
"$setOnInsert": bson.M{
|
|
|
|
|
"accid": newaccid,
|
|
|
|
|
"create": createtime,
|
|
|
|
|
},
|
|
|
|
|
}, options.FindOneAndUpdate().SetReturnDocument(options.After).SetUpsert(true).SetProjection(bson.M{"accid": 1, "create": 1}))
|
|
|
|
|
if err != nil {
|
|
|
|
|
logger.Error("authorize failed. Update sh.ServiceName err:", err)
|
|
|
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
|
|
|
return
|
|
|
|
|
}
|
2023-05-24 12:16:03 +09:00
|
|
|
|
2023-08-31 17:24:21 +09:00
|
|
|
accid := account["accid"].(primitive.ObjectID)
|
|
|
|
|
oldcreate := account["create"].(primitive.DateTime)
|
|
|
|
|
newaccount := oldcreate == createtime
|
2023-05-24 12:16:03 +09:00
|
|
|
|
2023-12-28 16:55:38 +09:00
|
|
|
if bi, ok := sh.bl.get(accid); ok {
|
2023-08-31 17:24:21 +09:00
|
|
|
// 블럭된 계정. 블락 정보를 알려준다.
|
|
|
|
|
w.Header().Add("MG-ACCOUNTBLOCK-START", strconv.FormatInt(bi.Start.Time().Unix(), 10))
|
|
|
|
|
w.Header().Add("MG-ACCOUNTBLOCK-END", strconv.FormatInt(bi.End.Time().Unix(), 10))
|
|
|
|
|
w.WriteHeader(http.StatusUnauthorized)
|
|
|
|
|
return
|
|
|
|
|
}
|
2023-05-24 12:16:03 +09:00
|
|
|
|
2024-04-22 17:58:53 +09:00
|
|
|
sk, err = sh.sessionProvider.New(&session.Authorization{
|
2023-08-31 17:24:21 +09:00
|
|
|
Account: accid,
|
2024-07-10 14:54:13 +09:00
|
|
|
Platform: reqauthtype,
|
2023-08-31 17:24:21 +09:00
|
|
|
Uid: uid,
|
|
|
|
|
Email: email,
|
|
|
|
|
})
|
|
|
|
|
if err != nil {
|
|
|
|
|
logger.Error("authorize failed. sessionProvider.New err:", err)
|
|
|
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
|
|
|
return
|
|
|
|
|
}
|
2023-05-24 12:16:03 +09:00
|
|
|
|
2023-08-31 17:24:21 +09:00
|
|
|
output := map[string]any{
|
|
|
|
|
"sk": sk,
|
|
|
|
|
"expirein": sh.sessionTTL.Seconds(),
|
|
|
|
|
"newAccount": newaccount,
|
|
|
|
|
"accid": accid.Hex(),
|
|
|
|
|
}
|
2024-07-10 14:54:13 +09:00
|
|
|
if len(reqauthtype) == 0 {
|
2023-08-31 17:24:21 +09:00
|
|
|
output["noauth"] = true
|
2023-05-24 12:16:03 +09:00
|
|
|
}
|
2023-09-19 18:50:45 +09:00
|
|
|
|
2024-07-15 12:37:52 +09:00
|
|
|
if link["_ts"] != nil {
|
|
|
|
|
delts := link["_ts"].(primitive.DateTime)
|
|
|
|
|
if !delts.Time().IsZero() {
|
|
|
|
|
// 삭제된 계정. 삭제 되었다고 알려주자
|
|
|
|
|
w.Header().Add("MG-ACCOUNT-DELETED", "TRUE")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-19 18:50:45 +09:00
|
|
|
json.NewEncoder(w).Encode(output)
|
2023-05-24 12:16:03 +09:00
|
|
|
}
|
|
|
|
|
|
2023-08-16 21:44:19 +09:00
|
|
|
func (sh *serviceDescription) findVersionSplit(version string) []byte {
|
|
|
|
|
if len(version) > 0 {
|
|
|
|
|
for k, v := range sh.divisionsSplits {
|
|
|
|
|
if strings.HasPrefix(version, k) {
|
|
|
|
|
if version == k || version[len(k)] == '.' {
|
|
|
|
|
return v
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-08-18 13:56:34 +09:00
|
|
|
return sh.divisionsSplits["default"]
|
2023-08-16 21:44:19 +09:00
|
|
|
}
|
|
|
|
|
|
2024-07-15 12:37:52 +09:00
|
|
|
func (sh *serviceDescription) delacc(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
defer func() {
|
|
|
|
|
s := recover()
|
|
|
|
|
if s != nil {
|
|
|
|
|
logger.Error(s)
|
|
|
|
|
}
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
if r.Method != "GET" {
|
|
|
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
queryvals := r.URL.Query()
|
|
|
|
|
sType := queryvals.Get("stype")
|
|
|
|
|
sId := queryvals.Get("sid")
|
|
|
|
|
sk := queryvals.Get("sk")
|
|
|
|
|
cancel := queryvals.Has("cancel")
|
|
|
|
|
|
|
|
|
|
authInfo, err := sh.sessionProvider.Query(sk)
|
|
|
|
|
if err != nil {
|
|
|
|
|
logger.Println("sessionProvider.Query return err :", err)
|
|
|
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
originAuthType := sType
|
2024-07-16 10:54:04 +09:00
|
|
|
if !*devflag || len(sType) != 0 {
|
|
|
|
|
sType, sId, err = sh.getProviderInfo(sType, sId)
|
|
|
|
|
if err != nil {
|
|
|
|
|
logger.Error("delacc failed. getProviderInfo err :", err)
|
|
|
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
|
|
|
return
|
|
|
|
|
}
|
2024-07-15 12:37:52 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if authInfo.Uid != sId || authInfo.Platform != sType {
|
|
|
|
|
logger.Println("delacc failed. session key is not correct :", authInfo, queryvals)
|
|
|
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
linkidMap, err := sh.mongoClient.FindAll(CollectionAccount, bson.M{"accid": authInfo.Account}, options.Find().SetProjection(bson.M{"_id": 1}))
|
|
|
|
|
if err != nil {
|
|
|
|
|
logger.Error("delacc failed. FindAll account err :", err)
|
|
|
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var linkidAry primitive.A
|
|
|
|
|
for _, linkid := range linkidMap {
|
|
|
|
|
linkidAry = append(linkidAry, linkid["_id"].(primitive.ObjectID))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
delfilter := primitive.M{"_id": bson.M{"$in": linkidAry}}
|
|
|
|
|
var delop primitive.M
|
|
|
|
|
if !cancel {
|
|
|
|
|
curtime := time.Now().UTC()
|
2024-07-16 10:54:04 +09:00
|
|
|
if *devflag && len(sType) == 0 {
|
|
|
|
|
curtime = curtime.Add(time.Second * time.Duration(10-config.AccDelTTL))
|
|
|
|
|
}
|
2024-07-15 12:37:52 +09:00
|
|
|
delop = primitive.M{"$set": primitive.M{"_ts": primitive.NewDateTimeFromTime(curtime)}}
|
|
|
|
|
|
|
|
|
|
if originAuthType == AuthPlatformFirebaseAuth {
|
2024-07-15 19:22:53 +09:00
|
|
|
if sType == "guest" {
|
|
|
|
|
logger.Error("delacc failed. cannot delete a guest account.")
|
|
|
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
|
|
|
return
|
|
|
|
|
}
|
2024-07-15 12:37:52 +09:00
|
|
|
sh.mongoClient.Delete(CollectionFirebaseUserInfo, bson.M{"firebaseuserid": sId})
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
delfilter["platform"] = sType
|
|
|
|
|
targetLinkId, err := sh.mongoClient.FindAll(CollectionLink, delfilter, options.Find().SetProjection(bson.M{"_id": 1}))
|
|
|
|
|
if len(targetLinkId) != 1 {
|
|
|
|
|
logger.Error("delacc failed. FindAll link err :", err)
|
|
|
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
delfilter = primitive.M{"_id": targetLinkId[0]["_id"].(primitive.ObjectID)}
|
|
|
|
|
delop = primitive.M{"$unset": primitive.M{"_ts": true}}
|
|
|
|
|
}
|
|
|
|
|
updated, _, err := sh.mongoClient.Update(CollectionAccount, delfilter, delop, options.Update().SetUpsert(false))
|
|
|
|
|
if !updated || err != nil {
|
|
|
|
|
logger.Error("delacc failed. Update CollectionAccount timestamp err :", err)
|
|
|
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
updated, _, err = sh.mongoClient.Update(CollectionLink, delfilter, delop, options.Update().SetUpsert(false))
|
|
|
|
|
if !updated || err != nil {
|
|
|
|
|
logger.Error("delacc failed. Update CollectionLink timestamp err :", err)
|
|
|
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
logger.Println("delacc success :", linkidMap)
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-25 22:08:22 +09:00
|
|
|
func (sh *serviceDescription) serveHTTP_dev(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
if strings.HasSuffix(r.URL.Path, "/auth") {
|
|
|
|
|
sh.authorize_dev(w, r)
|
|
|
|
|
} else {
|
|
|
|
|
sh.serveHTTP(w, r)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-16 21:44:19 +09:00
|
|
|
func (sh *serviceDescription) serveHTTP(w http.ResponseWriter, r *http.Request) {
|
2023-05-24 12:16:03 +09:00
|
|
|
defer func() {
|
|
|
|
|
s := recover()
|
|
|
|
|
if s != nil {
|
|
|
|
|
logger.Error(s)
|
|
|
|
|
}
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
defer func() {
|
|
|
|
|
io.Copy(io.Discard, r.Body)
|
|
|
|
|
r.Body.Close()
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
if strings.HasSuffix(r.URL.Path, "/auth") {
|
|
|
|
|
sh.authorize(w, r)
|
|
|
|
|
} else if strings.HasSuffix(r.URL.Path, "/link") {
|
|
|
|
|
sh.link(w, r)
|
2023-06-28 16:10:28 +09:00
|
|
|
} else if strings.HasSuffix(r.URL.Path, "/unlink") {
|
|
|
|
|
sh.unlink(w, r)
|
|
|
|
|
} else if strings.HasSuffix(r.URL.Path, "/linkinfo") {
|
|
|
|
|
sh.linkinfo(w, r)
|
2024-01-10 07:37:06 +09:00
|
|
|
} else if strings.HasSuffix(r.URL.Path, "/emailinfo") {
|
|
|
|
|
sh.emailinfo(w, r)
|
2024-07-15 12:37:52 +09:00
|
|
|
} else if strings.HasSuffix(r.URL.Path, "/delacc") {
|
|
|
|
|
sh.delacc(w, r)
|
2023-06-23 16:43:20 +09:00
|
|
|
} else if strings.HasSuffix(r.URL.Path, "/divs") {
|
2023-06-28 16:10:28 +09:00
|
|
|
// TODO : 세션키와 authtoken을 헤더로 받아서 accid 조회
|
2023-06-23 16:43:20 +09:00
|
|
|
queryvals := r.URL.Query()
|
|
|
|
|
sk := queryvals.Get("sk")
|
|
|
|
|
|
|
|
|
|
//if len(token) == 0 || len(sk) == 0 {
|
|
|
|
|
if len(sk) == 0 {
|
|
|
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO : 각 서버에 있는 자산? 캐릭터 정보를 보여줘야 하나. 뭘 보여줄지는 프로젝트에 문의
|
|
|
|
|
// 일단 서버 종류만 내려보내자
|
|
|
|
|
// 세션키가 있는지 확인
|
2023-08-30 17:04:00 +09:00
|
|
|
authInfo, err := sh.sessionProvider.Query(sk)
|
|
|
|
|
if err != nil {
|
|
|
|
|
logger.Println("sessionProvider.Query return err :", err)
|
|
|
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-04 14:37:58 +09:00
|
|
|
if authInfo.Account.IsZero() {
|
2023-06-23 16:43:20 +09:00
|
|
|
logger.Println("sessionkey is not valid :", sk)
|
|
|
|
|
w.WriteHeader(http.StatusUnauthorized)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-16 21:44:19 +09:00
|
|
|
version := queryvals.Get("version")
|
|
|
|
|
w.Write(sh.findVersionSplit(version))
|
2023-06-23 16:43:20 +09:00
|
|
|
} else if strings.HasSuffix(r.URL.Path, "/addr") {
|
2023-05-24 12:16:03 +09:00
|
|
|
queryvals := r.URL.Query()
|
|
|
|
|
sk := queryvals.Get("sk")
|
|
|
|
|
|
|
|
|
|
//if len(token) == 0 || len(sk) == 0 {
|
|
|
|
|
if len(sk) == 0 {
|
|
|
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO : 각 서버에 있는 자산? 캐릭터 정보를 보여줘야 하나. 뭘 보여줄지는 프로젝트에 문의
|
|
|
|
|
// 일단 서버 종류만 내려보내자
|
|
|
|
|
// 세션키가 있는지 확인
|
2023-08-30 17:04:00 +09:00
|
|
|
authInfo, err := sh.sessionProvider.Query(sk)
|
|
|
|
|
if err != nil {
|
|
|
|
|
logger.Println("sessionProvider.Query return err :", err)
|
|
|
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-04 14:37:58 +09:00
|
|
|
if authInfo.Account.IsZero() {
|
2023-05-28 22:13:10 +09:00
|
|
|
logger.Println("sessionkey is not valid :", sk)
|
2023-06-19 14:31:34 +09:00
|
|
|
w.WriteHeader(http.StatusUnauthorized)
|
2023-05-24 12:16:03 +09:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-23 16:43:20 +09:00
|
|
|
divname := queryvals.Get("div")
|
|
|
|
|
divname = strings.Trim(divname, `"`)
|
|
|
|
|
div := sh.Divisions[divname]
|
2024-02-04 15:23:33 +09:00
|
|
|
var addrresp string
|
2023-06-23 16:43:20 +09:00
|
|
|
if div != nil {
|
2024-02-04 15:23:33 +09:00
|
|
|
logger.Println("/addr :", divname, div.State)
|
|
|
|
|
|
2023-06-23 16:43:20 +09:00
|
|
|
switch div.State {
|
|
|
|
|
case DivisionState_FullOpen:
|
2024-02-04 15:23:33 +09:00
|
|
|
addrresp = fmt.Sprintf(`{"service":"%s"}`, div.Url)
|
|
|
|
|
//w.Write([]byte(fmt.Sprintf(`{"service":"%s"}`, div.Url)))
|
2023-06-23 16:43:20 +09:00
|
|
|
|
|
|
|
|
case DivisionState_RestrictedOpen:
|
|
|
|
|
// 점검중이면 whitelist만 입장 가능
|
2023-08-30 17:04:00 +09:00
|
|
|
authInfo, err := sh.sessionProvider.Query(sk)
|
|
|
|
|
if err != nil {
|
|
|
|
|
logger.Println("sessionProvider.Query return err :", err)
|
|
|
|
|
w.WriteHeader(http.StatusInternalServerError)
|
2023-06-23 16:43:20 +09:00
|
|
|
return
|
|
|
|
|
}
|
2023-08-30 17:04:00 +09:00
|
|
|
|
|
|
|
|
wm := &whitelistmember{Email: authInfo.Email, Platform: authInfo.Platform}
|
2023-12-28 16:55:38 +09:00
|
|
|
if _, ok := sh.wl.get(wm.Key()); ok {
|
2023-06-23 16:43:20 +09:00
|
|
|
// qa 권한이면 입장 가능
|
2024-02-04 15:23:33 +09:00
|
|
|
addrresp = fmt.Sprintf(`{"service":"%s"}`, div.Url)
|
|
|
|
|
//w.Write([]byte(fmt.Sprintf(`{"service":"%s"}`, div.Url)))
|
2023-06-23 16:43:20 +09:00
|
|
|
} else if div.Maintenance != nil {
|
|
|
|
|
// 권한이 없으므로 공지
|
2024-02-04 15:23:33 +09:00
|
|
|
addrresp = fmt.Sprintf(`{"notice":"%s"}`, div.Maintenance.link)
|
|
|
|
|
//w.Write([]byte(fmt.Sprintf(`{"notice":"%s"}`, div.Maintenance.link)))
|
2023-06-23 16:43:20 +09:00
|
|
|
} else {
|
|
|
|
|
logger.Println("div.Maintenance is nil :", divname)
|
|
|
|
|
}
|
2023-05-28 22:13:10 +09:00
|
|
|
|
2023-06-23 16:43:20 +09:00
|
|
|
case DivisionState_Maintenance:
|
|
|
|
|
// 점검중. 아무도 못들어감
|
|
|
|
|
if div.Maintenance != nil {
|
2024-02-04 15:23:33 +09:00
|
|
|
logger.Println("/addr :", divname, div.State, *div.Maintenance)
|
|
|
|
|
addrresp = fmt.Sprintf(`{"notice":"%s"}`, div.Maintenance.link)
|
|
|
|
|
//w.Write([]byte(fmt.Sprintf(`{"notice":"%s"}`, div.Maintenance.link)))
|
2023-06-23 16:43:20 +09:00
|
|
|
} else {
|
|
|
|
|
logger.Println("div.Maintenance is nil :", divname)
|
2023-05-28 22:13:10 +09:00
|
|
|
}
|
|
|
|
|
}
|
2024-02-04 15:23:33 +09:00
|
|
|
logger.Println("/addr resp :", addrresp)
|
|
|
|
|
w.Write([]byte(addrresp))
|
2023-05-28 22:13:10 +09:00
|
|
|
} else {
|
2023-11-16 19:58:24 +09:00
|
|
|
logger.Println("div is not found :", divname, sh.Divisions)
|
2023-12-06 16:35:55 +09:00
|
|
|
logger.Println("check maingate database 'service.divisions' :", config.Mongo)
|
2023-06-23 16:43:20 +09:00
|
|
|
w.WriteHeader(http.StatusBadRequest)
|
2023-05-28 22:13:10 +09:00
|
|
|
}
|
2023-06-23 16:43:20 +09:00
|
|
|
} else {
|
|
|
|
|
logger.Println("??? :", r.URL.Path)
|
|
|
|
|
w.WriteHeader(http.StatusBadRequest)
|
2023-05-24 12:16:03 +09:00
|
|
|
}
|
|
|
|
|
}
|