maingate - 연결된 계정 숫자 조회, 연결 끊는 API 추가

This commit is contained in:
2023-06-28 16:10:28 +09:00
parent 70d775e0fc
commit cb08ecb53a
3 changed files with 166 additions and 0 deletions

View File

@ -1,6 +1,7 @@
{ {
"maingate_mongodb_url": "mongodb://...", "maingate_mongodb_url": "mongodb://...",
"autologin_ttl": 604800, "autologin_ttl": 604800,
"maximum_num_link_account": 10,
"redirect_base_url": "", "redirect_base_url": "",
"google_client_id" : "", "google_client_id" : "",
"google_client_secret" : "", "google_client_secret" : "",

View File

@ -121,6 +121,7 @@ type maingateConfig struct {
Mongo string `json:"maingate_mongodb_url"` Mongo string `json:"maingate_mongodb_url"`
SessionTTL int64 `json:"maingate_session_ttl"` SessionTTL int64 `json:"maingate_session_ttl"`
Autologin_ttl int64 `json:"autologin_ttl"` Autologin_ttl int64 `json:"autologin_ttl"`
MaximumNumLinkAccount int64 `json:"maximum_num_link_account"`
RedirectBaseUrl string `json:"redirect_base_url"` RedirectBaseUrl string `json:"redirect_base_url"`
GoogleClientId string `json:"google_client_id"` GoogleClientId string `json:"google_client_id"`
GoogleClientSecret string `json:"google_client_secret"` GoogleClientSecret string `json:"google_client_secret"`
@ -326,6 +327,12 @@ func (mg *Maingate) prepare(context context.Context) (err error) {
return err return err
} }
if err = mg.mongoClient.MakeIndices(CollectionAccount, map[string]bson.D{
"accid": {{Key: "accid", Value: 1}},
}); err != nil {
return err
}
if err = mg.mongoClient.MakeUniqueIndices(CollectionFile, map[string]bson.D{ if err = mg.mongoClient.MakeUniqueIndices(CollectionFile, map[string]bson.D{
"sk": {{Key: "service", Value: 1}, {Key: "key", Value: 1}}, "sk": {{Key: "service", Value: 1}, {Key: "key", Value: 1}},
}); err != nil { }); err != nil {

View File

@ -1,6 +1,7 @@
package core package core
import ( import (
"context"
"crypto/md5" "crypto/md5"
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
@ -142,6 +143,8 @@ type serviceDescription struct {
wl *whitelist wl *whitelist
mongoClient common.MongoClient mongoClient common.MongoClient
sessionTTL time.Duration sessionTTL time.Duration
MaximumNumLinkAccount int64
serviceCodeBytes []byte serviceCodeBytes []byte
getUserBrowserInfo func(r *http.Request) (string, error) getUserBrowserInfo func(r *http.Request) (string, error)
getUserTokenWithCheck func(platform string, userid string, brinfo string) (usertokeninfo, error) getUserTokenWithCheck func(platform string, userid string, brinfo string) (usertokeninfo, error)
@ -255,6 +258,7 @@ func (sh *serviceDescription) prepare(mg *Maingate) error {
devstr2 := string(divmarshaled2) devstr2 := string(divmarshaled2)
sh.divisionsForUsersSerialized = unsafe.Pointer(&devstr2) sh.divisionsForUsersSerialized = unsafe.Pointer(&devstr2)
sh.MaximumNumLinkAccount = mg.maingateConfig.MaximumNumLinkAccount
sh.mongoClient = mg.mongoClient sh.mongoClient = mg.mongoClient
sh.auths = mg.auths sh.auths = mg.auths
sh.sessionTTL = time.Duration(mg.SessionTTL * int64(time.Second)) sh.sessionTTL = time.Duration(mg.SessionTTL * int64(time.Second))
@ -403,6 +407,155 @@ func (sh *serviceDescription) link(w http.ResponseWriter, r *http.Request) {
logger.Println("link success :", r.URL.Query()) logger.Println("link success :", r.URL.Query())
} }
// == 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")
authInfo := sh.auths.Find(sk)
if authInfo == nil {
// 잘못된 세션
logger.Println("linkinfo failed. session key is not valid :", sk)
w.WriteHeader(http.StatusBadRequest)
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 {
logger.Println("unlink failed. session key is not correct :", *authInfo, queryvals)
w.WriteHeader(http.StatusBadRequest)
return
}
numRecord, err := sh.mongoClient.Collection(CollectionAccount).CountDocuments(context.Background(), bson.M{
"accid": authInfo.Accid,
}, 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")
authInfo := sh.auths.Find(sk)
if authInfo == nil {
// 잘못된 세션
logger.Println("linkinfo failed. session key is not valid :", sk)
w.WriteHeader(http.StatusBadRequest)
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 {
logger.Println("linkinfo failed. session key is not correct :", *authInfo, queryvals)
w.WriteHeader(http.StatusBadRequest)
return
}
numRecord, err := sh.mongoClient.Collection(CollectionAccount).CountDocuments(context.Background(), bson.M{
"accid": authInfo.Accid,
}, 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)))
}
func (sh *serviceDescription) isAdmin(email string) bool { func (sh *serviceDescription) isAdmin(email string) bool {
ptr := atomic.LoadPointer(&sh.admins) ptr := atomic.LoadPointer(&sh.admins)
admins := *(*[]string)(ptr) admins := *(*[]string)(ptr)
@ -618,7 +771,12 @@ func (sh *serviceDescription) ServeHTTP(w http.ResponseWriter, r *http.Request)
sh.authorize(w, r) sh.authorize(w, r)
} else if strings.HasSuffix(r.URL.Path, "/link") { } else if strings.HasSuffix(r.URL.Path, "/link") {
sh.link(w, r) sh.link(w, r)
} else if strings.HasSuffix(r.URL.Path, "/unlink") {
sh.unlink(w, r)
} else if strings.HasSuffix(r.URL.Path, "/linkinfo") {
sh.linkinfo(w, r)
} else if strings.HasSuffix(r.URL.Path, "/divs") { } else if strings.HasSuffix(r.URL.Path, "/divs") {
// TODO : 세션키와 authtoken을 헤더로 받아서 accid 조회
queryvals := r.URL.Query() queryvals := r.URL.Query()
sk := queryvals.Get("sk") sk := queryvals.Get("sk")