Compare commits
89 Commits
7639c749dc
...
kd-live
| Author | SHA1 | Date | |
|---|---|---|---|
| 2d060fe117 | |||
| 231b1a35d5 | |||
| 845784d204 | |||
| 424c8be420 | |||
| ce39e8d878 | |||
| 54c727117b | |||
| 7816fd56c0 | |||
| 564a2ee14a | |||
| cbcae00c77 | |||
| 28dc84769d | |||
| 0c678947cd | |||
| dbd0a7bf5f | |||
| 86247e053d | |||
| 757c6d312c | |||
| e37a974d9c | |||
| 470591cb44 | |||
| 38114769b3 | |||
| b05473a1c6 | |||
| 0fff694e8a | |||
| d8713298c4 | |||
| 763b0fc4bd | |||
| d8e18d7ffc | |||
| 381f1edb80 | |||
| a8e448b8ca | |||
| 9b0e3a5d5b | |||
| 5757a81cb8 | |||
| c4b8e630dc | |||
| 43b0242652 | |||
| 893744a1ab | |||
| 192cc569b4 | |||
| 56e6608537 | |||
| 0053033e32 | |||
| d1ff6a56fc | |||
| 114461c51d | |||
| 117a3e5d90 | |||
| fafc463f2a | |||
| e2bec481f0 | |||
| 89e7d35b5a | |||
| fe662c5355 | |||
| 6767a37704 | |||
| 2ea035a43b | |||
| 2a1ad499ed | |||
| 5cc6ddc8f1 | |||
| 0e070221f8 | |||
| d2e06961b9 | |||
| 28092fcf17 | |||
| c43c10982c | |||
| 02c4f9e3d1 | |||
| 1db22730aa | |||
| 869fa48d74 | |||
| 7470f8e001 | |||
| fc70a9482c | |||
| 9ccd97564a | |||
| 4958cb0b93 | |||
| 9c14480be7 | |||
| daf3e3f027 | |||
| 2de82b9d2a | |||
| 00c2d6e205 | |||
| 87d922c558 | |||
| 0be7adefe3 | |||
| 3a9f81f1cb | |||
| a97b9f0983 | |||
| 9edea29983 | |||
| 8e908982a8 | |||
| 6b68d918ba | |||
| 3216e2620a | |||
| f66904d428 | |||
| 8d70777269 | |||
| 15ead6b0bc | |||
| 97636ce31d | |||
| 2b4becdb61 | |||
| 429bbd1e7a | |||
| 1c397da77a | |||
| 5502c4d744 | |||
| cb793092e9 | |||
| 13f6492e5f | |||
| f739eb3a8b | |||
| c95d7747cd | |||
| 841dad4992 | |||
| ff7d56152e | |||
| 2acca6dbe8 | |||
| 484db90037 | |||
| b06eb86578 | |||
| 9704decb7a | |||
| 767d6bf002 | |||
| 1f7421dd2e | |||
| 53701d61f8 | |||
| 6d02eb092c | |||
| 7bee78a875 |
@ -1,9 +1,7 @@
|
|||||||
{
|
{
|
||||||
"maingate_mongodb_url": "mongodb://...",
|
"maingate_mongodb_url": "mongodb://...",
|
||||||
"session_storage": "",
|
|
||||||
"session_ttl" : 3600,
|
|
||||||
|
|
||||||
"autologin_ttl": 604800,
|
"autologin_ttl": 604800,
|
||||||
|
"acc_del_ttl": 7776000,
|
||||||
"maximum_num_link_account": 10,
|
"maximum_num_link_account": 10,
|
||||||
"redirect_base_url": "",
|
"redirect_base_url": "",
|
||||||
"google_client_id" : "",
|
"google_client_id" : "",
|
||||||
|
|||||||
88
core/api.go
88
core/api.go
@ -161,14 +161,7 @@ func (caller apiCaller) uploadAPI(w http.ResponseWriter, r *http.Request) error
|
|||||||
func (caller apiCaller) blockAPI(w http.ResponseWriter, r *http.Request) error {
|
func (caller apiCaller) blockAPI(w http.ResponseWriter, r *http.Request) error {
|
||||||
mg := caller.mg
|
mg := caller.mg
|
||||||
if r.Method == "GET" {
|
if r.Method == "GET" {
|
||||||
target, ok := gocommon.ReadObjectIDFormValue(r.Form, "accid")
|
|
||||||
if ok {
|
|
||||||
json.NewEncoder(w).Encode(mg.bl.all())
|
json.NewEncoder(w).Encode(mg.bl.all())
|
||||||
} else if !target.IsZero() {
|
|
||||||
if blocked, ok := mg.bl.get(target); ok && blocked != nil {
|
|
||||||
json.NewEncoder(w).Encode(blocked)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if r.Method == "PUT" {
|
} else if r.Method == "PUT" {
|
||||||
body, _ := io.ReadAll(r.Body)
|
body, _ := io.ReadAll(r.Body)
|
||||||
|
|
||||||
@ -199,8 +192,6 @@ func (caller apiCaller) blockAPI(w http.ResponseWriter, r *http.Request) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
mg.sessionProvider.Delete(accid)
|
|
||||||
} else if r.Method == "DELETE" {
|
} else if r.Method == "DELETE" {
|
||||||
id := r.URL.Query().Get("id")
|
id := r.URL.Query().Get("id")
|
||||||
|
|
||||||
@ -223,6 +214,8 @@ func (caller apiCaller) blockAPI(w http.ResponseWriter, r *http.Request) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mg.mongoClient.Delete(CollectionAuth, bson.M{"_id": idobj})
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -239,7 +232,7 @@ func (caller apiCaller) whitelistAPI(w http.ResponseWriter, r *http.Request) err
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
member.ExpiredAt = 0
|
member.ExpiredAt = 0
|
||||||
|
member.Id = primitive.NilObjectID
|
||||||
_, _, err := mg.mongoClient.Update(CollectionWhitelist, bson.M{
|
_, _, err := mg.mongoClient.Update(CollectionWhitelist, bson.M{
|
||||||
"_id": primitive.NewObjectID(),
|
"_id": primitive.NewObjectID(),
|
||||||
}, bson.M{
|
}, bson.M{
|
||||||
@ -379,6 +372,11 @@ func (caller apiCaller) couponAPI(w http.ResponseWriter, r *http.Request) error
|
|||||||
logger.Println("begin listAllCouponNames")
|
logger.Println("begin listAllCouponNames")
|
||||||
listAllCouponNames(caller.mg.mongoClient, w, r)
|
listAllCouponNames(caller.mg.mongoClient, w, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case "DELETE":
|
||||||
|
// 쿠폰 삭제
|
||||||
|
logger.Println("begin deleteCoupon")
|
||||||
|
deleteCoupon(caller.mg.mongoClient, w, r)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -403,6 +401,40 @@ func (caller apiCaller) configAPI(w http.ResponseWriter, r *http.Request) error
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (caller apiCaller) lockcreatecharAPI(w http.ResponseWriter, r *http.Request) error {
|
||||||
|
mg, err := caller.mg.mongoClient.FindAll(CollectionService, bson.M{})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
haschr, _ := gocommon.ReadStringFormValue(r.Form, "haschr")
|
||||||
|
|
||||||
|
locked := make(map[string]any)
|
||||||
|
if haschr == "true" {
|
||||||
|
locked["lock"] = false
|
||||||
|
} else {
|
||||||
|
curregion, _ := gocommon.ReadStringFormValue(r.Form, "region")
|
||||||
|
|
||||||
|
for _, regioninfo := range mg {
|
||||||
|
region := regioninfo["divisions"].(primitive.M)
|
||||||
|
for idx, rl := range region {
|
||||||
|
if idx == curregion {
|
||||||
|
if rl.(primitive.M)["lockcreatechar"].(bool) {
|
||||||
|
locked["lock"] = true
|
||||||
|
} else {
|
||||||
|
locked["lock"] = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
create, _ := json.Marshal(locked)
|
||||||
|
w.Write(create)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type apiCaller struct {
|
type apiCaller struct {
|
||||||
userinfo map[string]any
|
userinfo map[string]any
|
||||||
globalAdmins map[string]bool
|
globalAdmins map[string]bool
|
||||||
@ -427,11 +459,28 @@ func (mg *Maingate) api(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
var userinfo map[string]any
|
var userinfo map[string]any
|
||||||
|
|
||||||
|
var apiTokenObj primitive.ObjectID
|
||||||
if !*devflag {
|
if !*devflag {
|
||||||
|
apiToken := r.Header.Get("MG-X-API-TOKEN")
|
||||||
|
if len(apiToken) > 0 {
|
||||||
|
if apiToken != mg.maingateConfig.ApiToken {
|
||||||
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
obj, err := primitive.ObjectIDFromHex(apiToken)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error(err)
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
apiTokenObj = obj
|
||||||
|
} else {
|
||||||
authheader := r.Header.Get("Authorization")
|
authheader := r.Header.Get("Authorization")
|
||||||
if len(authheader) == 0 {
|
if len(authheader) == 0 {
|
||||||
logger.Println("Authorization header is not valid :", authheader)
|
logger.Println("Authorization header is not valid :", authheader)
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -457,6 +506,7 @@ func (mg *Maingate) api(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ptr := atomic.LoadPointer(&mg.admins)
|
ptr := atomic.LoadPointer(&mg.admins)
|
||||||
adminsptr := (*globalAdmins)(ptr)
|
adminsptr := (*globalAdmins)(ptr)
|
||||||
@ -470,20 +520,6 @@ func (mg *Maingate) api(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var apiTokenObj primitive.ObjectID
|
|
||||||
if !*devflag {
|
|
||||||
apiToken := r.Header.Get("MG-X-API-TOKEN")
|
|
||||||
if len(apiToken) > 0 {
|
|
||||||
obj, err := primitive.ObjectIDFromHex(apiToken)
|
|
||||||
if err != nil {
|
|
||||||
logger.Error(err)
|
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
apiTokenObj = obj
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.Println("api call :", r.URL.Path, r.Method, r.URL.Query(), userinfo)
|
logger.Println("api call :", r.URL.Path, r.Method, r.URL.Query(), userinfo)
|
||||||
caller := apiCaller{
|
caller := apiCaller{
|
||||||
userinfo: userinfo,
|
userinfo: userinfo,
|
||||||
@ -509,6 +545,8 @@ func (mg *Maingate) api(w http.ResponseWriter, r *http.Request) {
|
|||||||
err = caller.blockAPI(w, r)
|
err = caller.blockAPI(w, r)
|
||||||
} else if strings.HasSuffix(r.URL.Path, "/coupon") {
|
} else if strings.HasSuffix(r.URL.Path, "/coupon") {
|
||||||
err = caller.couponAPI(w, r)
|
err = caller.couponAPI(w, r)
|
||||||
|
} else if strings.HasSuffix(r.URL.Path, "/lockcreatechar") {
|
||||||
|
err = caller.lockcreatecharAPI(w, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@ -30,6 +30,7 @@ type couponDoc struct {
|
|||||||
Total int64 `json:"total" bson:"total"`
|
Total int64 `json:"total" bson:"total"`
|
||||||
Remains []string `json:"remains,omitempty" bson:"remains,omitempty"`
|
Remains []string `json:"remains,omitempty" bson:"remains,omitempty"`
|
||||||
Used []string `json:"used,omitempty" bson:"used,omitempty"`
|
Used []string `json:"used,omitempty" bson:"used,omitempty"`
|
||||||
|
Expire int64 `json:"expire" bson:"expire"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeCouponKey(roundnum uint32, uid []byte) string {
|
func makeCouponKey(roundnum uint32, uid []byte) string {
|
||||||
@ -44,17 +45,17 @@ func makeCouponKey(roundnum uint32, uid []byte) string {
|
|||||||
return fmt.Sprintf("%s-%s-%s-%s", hex.EncodeToString(final[0:2]), hex.EncodeToString(final[2:4]), hex.EncodeToString(final[4:6]), hex.EncodeToString(final[6:8]))
|
return fmt.Sprintf("%s-%s-%s-%s", hex.EncodeToString(final[0:2]), hex.EncodeToString(final[2:4]), hex.EncodeToString(final[4:6]), hex.EncodeToString(final[6:8]))
|
||||||
}
|
}
|
||||||
|
|
||||||
var r = rand.New(rand.NewSource(time.Now().UnixNano()))
|
|
||||||
|
|
||||||
func makeCouponCodes(name string, count int) (string, map[string]string) {
|
func makeCouponCodes(name string, count int) (string, map[string]string) {
|
||||||
checkunique := make(map[string]bool)
|
checkunique := make(map[string]bool)
|
||||||
keys := make(map[string]string)
|
keys := make(map[string]string)
|
||||||
uid := make([]byte, 4)
|
uid := make([]byte, 4)
|
||||||
|
|
||||||
roundHash, roundnum := coupon.MakeCouponRoundHash(name)
|
roundHash, roundnum := coupon.MakeCouponRoundHash(name)
|
||||||
|
seed := time.Now().UnixNano()
|
||||||
|
|
||||||
for len(keys) < count {
|
for len(keys) < count {
|
||||||
r.Read(uid)
|
rand.Seed(seed)
|
||||||
|
rand.Read(uid)
|
||||||
|
|
||||||
code := makeCouponKey(roundnum, uid)
|
code := makeCouponKey(roundnum, uid)
|
||||||
|
|
||||||
@ -62,6 +63,7 @@ func makeCouponCodes(name string, count int) (string, map[string]string) {
|
|||||||
checkunique[code] = true
|
checkunique[code] = true
|
||||||
keys[hex.EncodeToString(uid)] = code
|
keys[hex.EncodeToString(uid)] = code
|
||||||
}
|
}
|
||||||
|
seed = int64(binary.BigEndian.Uint32(uid))
|
||||||
}
|
}
|
||||||
return roundHash, keys
|
return roundHash, keys
|
||||||
}
|
}
|
||||||
@ -71,6 +73,7 @@ func generateCoupons(mongoClient gocommon.MongoClient, w http.ResponseWriter, r
|
|||||||
effect, _ := gocommon.ReadStringFormValue(r.Form, "effect")
|
effect, _ := gocommon.ReadStringFormValue(r.Form, "effect")
|
||||||
count, _ := gocommon.ReadIntegerFormValue(r.Form, "count")
|
count, _ := gocommon.ReadIntegerFormValue(r.Form, "count")
|
||||||
desc, _ := gocommon.ReadStringFormValue(r.Form, "desc")
|
desc, _ := gocommon.ReadStringFormValue(r.Form, "desc")
|
||||||
|
expire, _ := gocommon.ReadIntegerFormValue(r.Form, "expire")
|
||||||
|
|
||||||
if count == 0 {
|
if count == 0 {
|
||||||
logger.Println("[generateCoupons] count == 0")
|
logger.Println("[generateCoupons] count == 0")
|
||||||
@ -91,6 +94,7 @@ func generateCoupons(mongoClient gocommon.MongoClient, w http.ResponseWriter, r
|
|||||||
Effect: effect,
|
Effect: effect,
|
||||||
Desc: desc,
|
Desc: desc,
|
||||||
Total: -1,
|
Total: -1,
|
||||||
|
Expire: expire,
|
||||||
},
|
},
|
||||||
}, options.Update().SetUpsert(true)); err != nil {
|
}, options.Update().SetUpsert(true)); err != nil {
|
||||||
logger.Println("[generateCoupons] Update failed :", err)
|
logger.Println("[generateCoupons] Update failed :", err)
|
||||||
@ -153,6 +157,7 @@ func generateCoupons(mongoClient gocommon.MongoClient, w http.ResponseWriter, r
|
|||||||
Effect: effect,
|
Effect: effect,
|
||||||
Desc: desc,
|
Desc: desc,
|
||||||
Total: count,
|
Total: count,
|
||||||
|
Expire: expire,
|
||||||
},
|
},
|
||||||
}, options.Update().SetUpsert(true))
|
}, options.Update().SetUpsert(true))
|
||||||
}
|
}
|
||||||
@ -197,7 +202,12 @@ func downloadCoupons(mongoClient gocommon.MongoClient, w http.ResponseWriter, r
|
|||||||
roundnum := binary.BigEndian.Uint32(roundObj[:])
|
roundnum := binary.BigEndian.Uint32(roundObj[:])
|
||||||
var coupons []string
|
var coupons []string
|
||||||
for _, uid := range coupon.Remains {
|
for _, uid := range coupon.Remains {
|
||||||
coupons = append(coupons, makeCouponKey(roundnum, []byte(uid)))
|
decUid, err := hex.DecodeString(uid)
|
||||||
|
if err != nil {
|
||||||
|
logger.Println("downloadCoupons Fail", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
coupons = append(coupons, makeCouponKey(roundnum, decUid))
|
||||||
}
|
}
|
||||||
|
|
||||||
enc := json.NewEncoder(w)
|
enc := json.NewEncoder(w)
|
||||||
@ -230,7 +240,7 @@ func queryCoupon(mongoClient gocommon.MongoClient, w http.ResponseWriter, r *htt
|
|||||||
var coupon couponDoc
|
var coupon couponDoc
|
||||||
if err := mongoClient.FindOneAs(CollectionCoupon, bson.M{
|
if err := mongoClient.FindOneAs(CollectionCoupon, bson.M{
|
||||||
"_id": roundObj,
|
"_id": roundObj,
|
||||||
}, &coupon, options.FindOne().SetProjection(bson.M{"effect": 1, "name": 1, "reason": 1, "total": 1, "desc": 1}).SetReturnKey(false)); err != nil {
|
}, &coupon, options.FindOne().SetProjection(bson.M{"effect": 1, "name": 1, "reason": 1, "total": 1, "desc": 1, "expire": 1}).SetReturnKey(false)); err != nil {
|
||||||
logger.Println("[queryCoupon] FindOneAs failed :", err)
|
logger.Println("[queryCoupon] FindOneAs failed :", err)
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
@ -274,8 +284,8 @@ func useCoupon(mongoClient gocommon.MongoClient, w http.ResponseWriter, r *http.
|
|||||||
round, _ = coupon.MakeCouponRoundHash(code)
|
round, _ = coupon.MakeCouponRoundHash(code)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1. 내가 이 라운드의 쿠폰을 쓴 적이 있나
|
// 쿠폰 사용 유무 검사
|
||||||
already, err := mongoClient.Exists(CollectionCouponUse, bson.M{
|
alreadyused, err := mongoClient.Exists(CollectionCouponUse, bson.M{
|
||||||
"_id": acc,
|
"_id": acc,
|
||||||
"rounds": round,
|
"rounds": round,
|
||||||
})
|
})
|
||||||
@ -285,7 +295,7 @@ func useCoupon(mongoClient gocommon.MongoClient, w http.ResponseWriter, r *http.
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if already {
|
if alreadyused {
|
||||||
// 이미 이 라운드의 쿠폰을 사용한 적이 있다.
|
// 이미 이 라운드의 쿠폰을 사용한 적이 있다.
|
||||||
w.WriteHeader(http.StatusConflict)
|
w.WriteHeader(http.StatusConflict)
|
||||||
return
|
return
|
||||||
@ -297,7 +307,7 @@ func useCoupon(mongoClient gocommon.MongoClient, w http.ResponseWriter, r *http.
|
|||||||
// 무한 쿠폰일 수 있으므로 존재하는지 확인
|
// 무한 쿠폰일 수 있으므로 존재하는지 확인
|
||||||
if err := mongoClient.FindOneAs(CollectionCoupon, bson.M{
|
if err := mongoClient.FindOneAs(CollectionCoupon, bson.M{
|
||||||
"_id": roundObj,
|
"_id": roundObj,
|
||||||
}, &coupon, options.FindOne().SetProjection(bson.M{"_id": 0, "effect": 1, "name": 1, "reason": 1, "total": 1})); err != nil {
|
}, &coupon, options.FindOne().SetProjection(bson.M{"_id": 0, "effect": 1, "name": 1, "total": 1, "expire": 1})); err != nil {
|
||||||
logger.Println(err)
|
logger.Println(err)
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
@ -309,9 +319,10 @@ func useCoupon(mongoClient gocommon.MongoClient, w http.ResponseWriter, r *http.
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 2. 쿠폰을 하나 꺼냄
|
// 쿠폰을 하나 꺼냄
|
||||||
matched, _, err := mongoClient.Update(CollectionCoupon, bson.M{
|
matched, _, err := mongoClient.Update(CollectionCoupon, bson.M{
|
||||||
"_id": roundObj,
|
"_id": roundObj,
|
||||||
|
"remains": key,
|
||||||
}, bson.M{
|
}, bson.M{
|
||||||
"$pull": bson.M{"remains": key},
|
"$pull": bson.M{"remains": key},
|
||||||
})
|
})
|
||||||
@ -327,18 +338,24 @@ func useCoupon(mongoClient gocommon.MongoClient, w http.ResponseWriter, r *http.
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. round의 효과 읽기
|
// round의 효과 읽기
|
||||||
if err := mongoClient.FindOneAndUpdateAs(CollectionCoupon, bson.M{
|
if err := mongoClient.FindOneAndUpdateAs(CollectionCoupon, bson.M{
|
||||||
"_id": roundObj,
|
"_id": roundObj,
|
||||||
}, bson.M{
|
}, bson.M{
|
||||||
"$push": bson.M{"used": key},
|
"$push": bson.M{"used": key},
|
||||||
}, &coupon, options.FindOneAndUpdate().SetProjection(bson.M{"effect": 1})); err != nil {
|
}, &coupon, options.FindOneAndUpdate().SetProjection(bson.M{"effect": 1, "expire": 1})); err != nil {
|
||||||
logger.Println(err)
|
logger.Println(err)
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if coupon.Expire < time.Now().Unix() {
|
||||||
|
// 쿠폰 만료시간 경과
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if len(coupon.Effect) == 0 {
|
if len(coupon.Effect) == 0 {
|
||||||
// 쿠폰이 없네?
|
// 쿠폰이 없네?
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
@ -369,3 +386,22 @@ func useCoupon(mongoClient gocommon.MongoClient, w http.ResponseWriter, r *http.
|
|||||||
|
|
||||||
w.Write([]byte(coupon.Effect))
|
w.Write([]byte(coupon.Effect))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func deleteCoupon(mongoClient gocommon.MongoClient, w http.ResponseWriter, r *http.Request) {
|
||||||
|
code, _ := gocommon.ReadStringFormValue(r.Form, "name")
|
||||||
|
if len(code) == 0 {
|
||||||
|
logger.Println("coupon delete code error")
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := mongoClient.Delete(CollectionCoupon, bson.M{
|
||||||
|
"name": code,
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
logger.Println("coupon delete error")
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -21,7 +21,7 @@ func TestMakeLocalUniqueId(t *testing.T) {
|
|||||||
fmt.Println(start.Time().Format(time.RFC3339))
|
fmt.Println(start.Time().Format(time.RFC3339))
|
||||||
fmt.Println(end.Time().Format(time.RFC3339))
|
fmt.Println(end.Time().Format(time.RFC3339))
|
||||||
|
|
||||||
mongoClient, err := gocommon.NewMongoClient(context.Background(), "mongodb://121.134.91.160:27018/?replicaSet=rs0&retrywrites=true")
|
mongoClient, err := gocommon.NewMongoClient(context.Background(), "mongodb://121.134.91.160:27018/mountain-maingate?replicaSet=rs0&retrywrites=true", "maingate")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
|
|||||||
206
core/maingate.go
206
core/maingate.go
@ -9,9 +9,11 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
"math/rand"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"runtime/debug"
|
||||||
"strings"
|
"strings"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"text/template"
|
"text/template"
|
||||||
@ -21,7 +23,6 @@ import (
|
|||||||
"repositories.action2quare.com/ayo/gocommon"
|
"repositories.action2quare.com/ayo/gocommon"
|
||||||
"repositories.action2quare.com/ayo/gocommon/flagx"
|
"repositories.action2quare.com/ayo/gocommon/flagx"
|
||||||
"repositories.action2quare.com/ayo/gocommon/logger"
|
"repositories.action2quare.com/ayo/gocommon/logger"
|
||||||
"repositories.action2quare.com/ayo/gocommon/session"
|
|
||||||
|
|
||||||
"github.com/golang-jwt/jwt"
|
"github.com/golang-jwt/jwt"
|
||||||
"go.mongodb.org/mongo-driver/bson"
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
@ -39,6 +40,7 @@ var noauth = flagx.Bool("noauth", false, "")
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
CollectionLink = gocommon.CollectionName("link")
|
CollectionLink = gocommon.CollectionName("link")
|
||||||
|
CollectionAuth = gocommon.CollectionName("auth")
|
||||||
CollectionWhitelist = gocommon.CollectionName("whitelist")
|
CollectionWhitelist = gocommon.CollectionName("whitelist")
|
||||||
CollectionService = gocommon.CollectionName("service")
|
CollectionService = gocommon.CollectionName("service")
|
||||||
CollectionAccount = gocommon.CollectionName("account")
|
CollectionAccount = gocommon.CollectionName("account")
|
||||||
@ -72,10 +74,58 @@ func SessionTTL() time.Duration {
|
|||||||
return sessionTTL
|
return sessionTTL
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type mongoAuthCell struct {
|
||||||
|
src *gocommon.Authinfo
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ac *mongoAuthCell) ToAuthinfo() *gocommon.Authinfo {
|
||||||
|
if ac.src == nil {
|
||||||
|
logger.Error("mongoAuthCell ToAuthinfo failed. ac.src is nil")
|
||||||
|
}
|
||||||
|
return ac.src
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ac *mongoAuthCell) ToBytes() []byte {
|
||||||
|
bt, _ := json.Marshal(ac.src)
|
||||||
|
return bt
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeAuthCollection(mongoClient gocommon.MongoClient, sessionTTL time.Duration) *gocommon.AuthCollection {
|
||||||
|
authcoll := gocommon.MakeAuthCollection(sessionTTL)
|
||||||
|
authcoll.SessionRemoved = func(sk string) {
|
||||||
|
skid, _ := primitive.ObjectIDFromHex(sk)
|
||||||
|
mongoClient.Delete(CollectionAuth, bson.M{
|
||||||
|
"sk": skid,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
authcoll.QuerySession = func(sk string, token string) gocommon.AuthinfoCell {
|
||||||
|
skid, _ := primitive.ObjectIDFromHex(sk)
|
||||||
|
var outcell mongoAuthCell
|
||||||
|
err := mongoClient.FindOneAs(CollectionAuth, bson.M{
|
||||||
|
"sk": skid,
|
||||||
|
}, &outcell.src, options.FindOne().SetHint("skonly"))
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("QuerySession failed :", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if outcell.src == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &outcell
|
||||||
|
}
|
||||||
|
|
||||||
|
return authcoll
|
||||||
|
}
|
||||||
|
|
||||||
type maingateConfig struct {
|
type maingateConfig struct {
|
||||||
session.SessionConfig `json:",inline"`
|
|
||||||
Mongo string `json:"maingate_mongodb_url"`
|
Mongo string `json:"maingate_mongodb_url"`
|
||||||
|
SessionTTL int64 `json:"maingate_session_ttl"`
|
||||||
|
ApiToken string `json:"maingate_api_token"`
|
||||||
Autologin_ttl int64 `json:"autologin_ttl"`
|
Autologin_ttl int64 `json:"autologin_ttl"`
|
||||||
|
AccDelTTL int64 `json:"acc_del_ttl"`
|
||||||
MaximumNumLinkAccount int64 `json:"maximum_num_link_account"`
|
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"`
|
||||||
@ -131,7 +181,7 @@ type Maingate struct {
|
|||||||
|
|
||||||
mongoClient gocommon.MongoClient
|
mongoClient gocommon.MongoClient
|
||||||
|
|
||||||
sessionProvider session.Provider
|
auths *gocommon.AuthCollection
|
||||||
//services servicelist
|
//services servicelist
|
||||||
serviceptr unsafe.Pointer
|
serviceptr unsafe.Pointer
|
||||||
admins unsafe.Pointer
|
admins unsafe.Pointer
|
||||||
@ -158,10 +208,6 @@ func New(ctx context.Context) (*Maingate, error) {
|
|||||||
admins.parse()
|
admins.parse()
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(config.SessionStorage) == 0 {
|
|
||||||
return nil, errors.New("maingate_session_storage is missing")
|
|
||||||
}
|
|
||||||
|
|
||||||
if config.SessionTTL == 0 {
|
if config.SessionTTL == 0 {
|
||||||
config.SessionTTL = 3600
|
config.SessionTTL = 3600
|
||||||
}
|
}
|
||||||
@ -256,96 +302,110 @@ func (mg *Maingate) discoverOpenIdConfiguration(name string, url string) error {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func makeErrorWithStack(err error) error {
|
||||||
|
return fmt.Errorf("%s\n%s", err.Error(), string(debug.Stack()))
|
||||||
|
}
|
||||||
|
|
||||||
func (mg *Maingate) prepare(context context.Context) (err error) {
|
func (mg *Maingate) prepare(context context.Context) (err error) {
|
||||||
if err := mg.discoverOpenIdConfiguration(AuthPlatformMicrosoft, "https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration"); err != nil {
|
if err := mg.discoverOpenIdConfiguration(AuthPlatformMicrosoft, "https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration"); err != nil {
|
||||||
return logger.ErrorWithCallStack(err)
|
return makeErrorWithStack(err)
|
||||||
}
|
}
|
||||||
if err := mg.discoverOpenIdConfiguration("google", "https://accounts.google.com/.well-known/openid-configuration"); err != nil {
|
if err := mg.discoverOpenIdConfiguration("google", "https://accounts.google.com/.well-known/openid-configuration"); err != nil {
|
||||||
return logger.ErrorWithCallStack(err)
|
return makeErrorWithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// redis에서 env를 가져온 후에
|
// redis에서 env를 가져온 후에
|
||||||
mg.mongoClient, err = gocommon.NewMongoClient(context, mg.Mongo)
|
mg.mongoClient, err = gocommon.NewMongoClient(context, mg.Mongo, "maingate")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return logger.ErrorWithCallStack(err)
|
return makeErrorWithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = mg.mongoClient.MakeUniqueIndices(CollectionCouponUse, map[string]bson.D{
|
if err = mg.mongoClient.MakeUniqueIndices(CollectionCouponUse, map[string]bson.D{
|
||||||
"idrounds": {{Key: "_id", Value: 1}, {Key: "rounds", Value: 1}},
|
"idrounds": {{Key: "_id", Value: 1}, {Key: "rounds", Value: 1}},
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return logger.ErrorWithCallStack(err)
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = mg.mongoClient.MakeUniqueIndices(CollectionAuth, map[string]bson.D{
|
||||||
|
"skonly": {{Key: "sk", Value: 1}},
|
||||||
|
}); err != nil {
|
||||||
|
return makeErrorWithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = mg.mongoClient.MakeUniqueIndices(CollectionLink, map[string]bson.D{
|
if err = mg.mongoClient.MakeUniqueIndices(CollectionLink, map[string]bson.D{
|
||||||
"platformuid": {{Key: "platform", Value: 1}, {Key: "uid", Value: 1}},
|
"platformuid": {{Key: "platform", Value: 1}, {Key: "uid", Value: 1}},
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return logger.ErrorWithCallStack(err)
|
return makeErrorWithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = mg.mongoClient.MakeUniqueIndices(CollectionLink, map[string]bson.D{
|
if err = mg.mongoClient.MakeUniqueIndices(CollectionLink, map[string]bson.D{
|
||||||
"emailplatform": {{Key: "email", Value: 1}, {Key: "platform", Value: 1}},
|
"emailplatform": {{Key: "email", Value: 1}, {Key: "platform", Value: 1}},
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return logger.ErrorWithCallStack(err)
|
return makeErrorWithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = mg.mongoClient.MakeIndices(CollectionAccount, map[string]bson.D{
|
if err = mg.mongoClient.MakeIndices(CollectionAccount, map[string]bson.D{
|
||||||
"accid": {{Key: "accid", Value: 1}},
|
"accid": {{Key: "accid", Value: 1}},
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return logger.ErrorWithCallStack(err)
|
return makeErrorWithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = mg.mongoClient.MakeUniqueIndices(CollectionFile, map[string]bson.D{
|
if err = mg.mongoClient.MakeUniqueIndices(CollectionFile, map[string]bson.D{
|
||||||
"keyonly": {{Key: "key", Value: 1}},
|
"keyonly": {{Key: "key", Value: 1}},
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return logger.ErrorWithCallStack(err)
|
return makeErrorWithStack(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = mg.mongoClient.MakeExpireIndex(CollectionAccount, int32(mg.AccDelTTL)); err != nil {
|
||||||
|
return makeErrorWithStack(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = mg.mongoClient.MakeExpireIndex(CollectionLink, int32(mg.AccDelTTL)); err != nil {
|
||||||
|
return makeErrorWithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete대신 _ts로 expire시킴. pipeline에 삭제 알려주기 위함
|
// Delete대신 _ts로 expire시킴. pipeline에 삭제 알려주기 위함
|
||||||
if err = mg.mongoClient.MakeExpireIndex(CollectionWhitelist, 10); err != nil {
|
if err = mg.mongoClient.MakeExpireIndex(CollectionWhitelist, 10); err != nil {
|
||||||
return logger.ErrorWithCallStack(err)
|
return makeErrorWithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if *devflag {
|
if err = mg.mongoClient.MakeExpireIndex(CollectionAuth, int32(mg.SessionTTL+300)); err != nil {
|
||||||
// 에러 체크하지 말것
|
return makeErrorWithStack(err)
|
||||||
mg.mongoClient.DropIndex(CollectionBlock, "codeaccid")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = mg.mongoClient.MakeExpireIndex(CollectionBlock, int32(3)); err != nil {
|
if err = mg.mongoClient.MakeExpireIndex(CollectionBlock, int32(3)); err != nil {
|
||||||
return logger.ErrorWithCallStack(err)
|
return makeErrorWithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = mg.mongoClient.MakeUniqueIndices(CollectionPlatformLoginToken, map[string]bson.D{
|
if err = mg.mongoClient.MakeUniqueIndices(CollectionPlatformLoginToken, map[string]bson.D{
|
||||||
"platformauthtoken": {{Key: "platform", Value: 1}, {Key: "key", Value: 1}},
|
"platformauthtoken": {{Key: "platform", Value: 1}, {Key: "key", Value: 1}},
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return logger.ErrorWithCallStack(err)
|
return makeErrorWithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = mg.mongoClient.MakeExpireIndex(CollectionPlatformLoginToken, int32(mg.SessionTTL+300)); err != nil {
|
if err = mg.mongoClient.MakeExpireIndex(CollectionPlatformLoginToken, int32(mg.SessionTTL+300)); err != nil {
|
||||||
return logger.ErrorWithCallStack(err)
|
return makeErrorWithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = mg.mongoClient.MakeUniqueIndices(CollectionUserToken, map[string]bson.D{
|
if err = mg.mongoClient.MakeUniqueIndices(CollectionUserToken, map[string]bson.D{
|
||||||
"platformusertoken": {{Key: "platform", Value: 1}, {Key: "userid", Value: 1}},
|
"platformusertoken": {{Key: "platform", Value: 1}, {Key: "userid", Value: 1}},
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return logger.ErrorWithCallStack(err)
|
return makeErrorWithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = mg.mongoClient.MakeUniqueIndices(CollectionGamepotUserInfo, map[string]bson.D{
|
if err = mg.mongoClient.MakeUniqueIndices(CollectionGamepotUserInfo, map[string]bson.D{
|
||||||
"gamepotuserid": {{Key: "gamepotuserid", Value: 1}},
|
"gamepotuserid": {{Key: "gamepotuserid", Value: 1}},
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return logger.ErrorWithCallStack(err)
|
return makeErrorWithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = mg.mongoClient.MakeUniqueIndices(CollectionFirebaseUserInfo, map[string]bson.D{
|
if err = mg.mongoClient.MakeUniqueIndices(CollectionFirebaseUserInfo, map[string]bson.D{
|
||||||
"firebaseuserid": {{Key: "firebaseuserid", Value: 1}},
|
"firebaseuserid": {{Key: "firebaseuserid", Value: 1}},
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return logger.ErrorWithCallStack(err)
|
return makeErrorWithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
mg.sessionProvider, err = session.NewProviderWithConfig(context, mg.SessionConfig)
|
mg.auths = makeAuthCollection(mg.mongoClient, time.Duration(mg.SessionTTL*int64(time.Second)))
|
||||||
if err != nil {
|
|
||||||
return logger.ErrorWithCallStack(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var preall []struct {
|
var preall []struct {
|
||||||
Link string `bson:"link"`
|
Link string `bson:"link"`
|
||||||
@ -354,7 +414,7 @@ func (mg *Maingate) prepare(context context.Context) (err error) {
|
|||||||
if err = mg.mongoClient.FindAllAs(CollectionFile, nil, &preall, options.Find().SetProjection(bson.M{
|
if err = mg.mongoClient.FindAllAs(CollectionFile, nil, &preall, options.Find().SetProjection(bson.M{
|
||||||
"link": 1,
|
"link": 1,
|
||||||
})); err != nil {
|
})); err != nil {
|
||||||
return logger.ErrorWithCallStack(err)
|
return makeErrorWithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, pre := range preall {
|
for _, pre := range preall {
|
||||||
@ -369,26 +429,27 @@ func (mg *Maingate) prepare(context context.Context) (err error) {
|
|||||||
"_id": pre.Id,
|
"_id": pre.Id,
|
||||||
}, &fulldoc)
|
}, &fulldoc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return logger.ErrorWithCallStack(err)
|
return makeErrorWithStack(err)
|
||||||
}
|
}
|
||||||
err = fulldoc.Save()
|
err = fulldoc.Save()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return logger.ErrorWithCallStack(err)
|
return makeErrorWithStack(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var whites []*whitelistmember
|
var whites []*whitelistmember
|
||||||
if err := mg.mongoClient.AllAs(CollectionWhitelist, &whites, options.Find().SetReturnKey(false)); err != nil {
|
if err := mg.mongoClient.AllAs(CollectionWhitelist, &whites, options.Find().SetReturnKey(false)); err != nil {
|
||||||
return logger.ErrorWithCallStack(err)
|
return makeErrorWithStack(err)
|
||||||
}
|
}
|
||||||
mg.wl.init(whites)
|
mg.wl.init(whites)
|
||||||
|
|
||||||
var blocks []*blockinfo
|
var blocks []*blockinfo
|
||||||
if err := mg.mongoClient.AllAs(CollectionBlock, &blocks); err != nil {
|
if err := mg.mongoClient.AllAs(CollectionBlock, &blocks); err != nil {
|
||||||
return logger.ErrorWithCallStack(err)
|
return makeErrorWithStack(err)
|
||||||
}
|
}
|
||||||
mg.bl.init(blocks)
|
mg.bl.init(blocks)
|
||||||
|
|
||||||
|
go watchAuthCollection(context, mg.auths, mg.mongoClient)
|
||||||
go mg.wl.watchCollection(context, CollectionWhitelist, mg.mongoClient)
|
go mg.wl.watchCollection(context, CollectionWhitelist, mg.mongoClient)
|
||||||
go mg.bl.watchCollection(context, CollectionBlock, mg.mongoClient)
|
go mg.bl.watchCollection(context, CollectionBlock, mg.mongoClient)
|
||||||
|
|
||||||
@ -398,7 +459,7 @@ func (mg *Maingate) prepare(context context.Context) (err error) {
|
|||||||
func (mg *Maingate) RegisterHandlers(ctx context.Context, serveMux *http.ServeMux, prefix string) error {
|
func (mg *Maingate) RegisterHandlers(ctx context.Context, serveMux *http.ServeMux, prefix string) error {
|
||||||
var allServices []*serviceDescription
|
var allServices []*serviceDescription
|
||||||
if err := mg.mongoClient.AllAs(CollectionService, &allServices, options.Find().SetReturnKey(false)); err != nil {
|
if err := mg.mongoClient.AllAs(CollectionService, &allServices, options.Find().SetReturnKey(false)); err != nil {
|
||||||
return logger.ErrorWithCallStack(err)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(allServices) > 0 {
|
if len(allServices) > 0 {
|
||||||
@ -417,7 +478,7 @@ func (mg *Maingate) RegisterHandlers(ctx context.Context, serveMux *http.ServeMu
|
|||||||
host, _ := os.Hostname()
|
host, _ := os.Hostname()
|
||||||
addrs, err := net.InterfaceAddrs()
|
addrs, err := net.InterfaceAddrs()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return logger.ErrorWithCallStack(err)
|
return err
|
||||||
}
|
}
|
||||||
ipaddr := "127.0.0.1"
|
ipaddr := "127.0.0.1"
|
||||||
for _, addr := range addrs {
|
for _, addr := range addrs {
|
||||||
@ -433,6 +494,7 @@ func (mg *Maingate) RegisterHandlers(ctx context.Context, serveMux *http.ServeMu
|
|||||||
DivisionForUser: DivisionForUser{
|
DivisionForUser: DivisionForUser{
|
||||||
Priority: 0,
|
Priority: 0,
|
||||||
State: DivisionState_FullOpen,
|
State: DivisionState_FullOpen,
|
||||||
|
LockCreateChar: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
Url: fmt.Sprintf("http://%s/warehouse", ipaddr),
|
Url: fmt.Sprintf("http://%s/warehouse", ipaddr),
|
||||||
@ -449,7 +511,7 @@ func (mg *Maingate) RegisterHandlers(ctx context.Context, serveMux *http.ServeMu
|
|||||||
}, options.Update().SetUpsert(true))
|
}, options.Update().SetUpsert(true))
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return logger.ErrorWithCallStack(err)
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -458,11 +520,12 @@ func (mg *Maingate) RegisterHandlers(ctx context.Context, serveMux *http.ServeMu
|
|||||||
mg.service().serveHTTP(w, r)
|
mg.service().serveHTTP(w, r)
|
||||||
})
|
})
|
||||||
serveMux.HandleFunc(gocommon.MakeHttpHandlerPattern(prefix, "api/"), mg.api)
|
serveMux.HandleFunc(gocommon.MakeHttpHandlerPattern(prefix, "api/"), mg.api)
|
||||||
|
serveMux.HandleFunc(gocommon.MakeHttpHandlerPattern(prefix, "query/"), mg.query)
|
||||||
|
|
||||||
configraw, _ := json.Marshal(mg.maingateConfig)
|
configraw, _ := json.Marshal(mg.maingateConfig)
|
||||||
var convertedConfig map[string]any
|
var convertedConfig map[string]any
|
||||||
if err := json.Unmarshal(configraw, &convertedConfig); err != nil {
|
if err := json.Unmarshal(configraw, &convertedConfig); err != nil {
|
||||||
return logger.ErrorWithCallStack(err)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
serveMux.HandleFunc(gocommon.MakeHttpHandlerPattern(prefix, "config"), func(w http.ResponseWriter, r *http.Request) {
|
serveMux.HandleFunc(gocommon.MakeHttpHandlerPattern(prefix, "config"), func(w http.ResponseWriter, r *http.Request) {
|
||||||
@ -495,7 +558,7 @@ func (mg *Maingate) RegisterHandlers(ctx context.Context, serveMux *http.ServeMu
|
|||||||
|
|
||||||
if err := os.MkdirAll("static", os.ModePerm); err != nil {
|
if err := os.MkdirAll("static", os.ModePerm); err != nil {
|
||||||
// 일반 엔드유저한테 오픈할 static 페이지
|
// 일반 엔드유저한테 오픈할 static 페이지
|
||||||
return logger.ErrorWithCallStack(err)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
cfsx := http.FileServer(http.Dir("console"))
|
cfsx := http.FileServer(http.Dir("console"))
|
||||||
@ -546,11 +609,59 @@ func (mg *Maingate) RegisterHandlers(ctx context.Context, serveMux *http.ServeMu
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (mg *Maingate) query(w http.ResponseWriter, r *http.Request) {
|
||||||
|
defer func() {
|
||||||
|
s := recover()
|
||||||
|
if s != nil {
|
||||||
|
logger.Error(s)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
io.Copy(io.Discard, r.Body)
|
||||||
|
r.Body.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
|
queryvals := r.URL.Query()
|
||||||
|
sk := queryvals.Get("sk")
|
||||||
|
|
||||||
|
if len(sk) == 0 {
|
||||||
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
info := mg.auths.Find(sk)
|
||||||
|
if info == nil {
|
||||||
|
logger.Println("session key is not valid :", sk)
|
||||||
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !*devflag {
|
||||||
|
apitoken := r.Header.Get("MG-X-API-TOKEN")
|
||||||
|
if len(apitoken) == 0 {
|
||||||
|
logger.Println("MG-X-API-TOKEN is missing")
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
apitokenObj, _ := primitive.ObjectIDFromHex(apitoken)
|
||||||
|
if !mg.service().isValidToken(apitokenObj) {
|
||||||
|
logger.Println("MG-X-API-TOKEN is invalid :", apitoken)
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bt, _ := json.Marshal(info)
|
||||||
|
w.Write(bt)
|
||||||
|
}
|
||||||
|
|
||||||
func (mg *Maingate) GeneratePlatformLoginNonceKey() string {
|
func (mg *Maingate) GeneratePlatformLoginNonceKey() string {
|
||||||
const allowed = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
const allowed = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
||||||
b := make([]byte, 52)
|
b := make([]byte, 52)
|
||||||
for i := range b {
|
for i := range b {
|
||||||
b[i] = allowed[r.Intn(len(allowed))]
|
b[i] = allowed[rand.Intn(len(allowed))]
|
||||||
}
|
}
|
||||||
return string(b)
|
return string(b)
|
||||||
}
|
}
|
||||||
@ -564,7 +675,7 @@ func (mg *Maingate) GetUserBrowserInfo(r *http.Request) (string, error) {
|
|||||||
|
|
||||||
cookie, err := r.Cookie("ActionSquareSessionExtraInfo")
|
cookie, err := r.Cookie("ActionSquareSessionExtraInfo")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", logger.ErrorWithCallStack(err)
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
//requestinfo := fmt.Sprintf("%s_%s", cookie.Value, host) //-- RemoteAddr체크는 로드밸런서 IP 찍히는 문제 때문에 제외한다.
|
//requestinfo := fmt.Sprintf("%s_%s", cookie.Value, host) //-- RemoteAddr체크는 로드밸런서 IP 찍히는 문제 때문에 제외한다.
|
||||||
@ -586,7 +697,7 @@ func (mg *Maingate) setUserToken(info usertokeninfo) error {
|
|||||||
"accesstoken_expire_time": info.accesstoken_expire_time,
|
"accesstoken_expire_time": info.accesstoken_expire_time,
|
||||||
},
|
},
|
||||||
}, options.Update().SetUpsert(true))
|
}, options.Update().SetUpsert(true))
|
||||||
return logger.ErrorWithCallStack(err)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mg *Maingate) getUserTokenWithCheck(platform string, userid string, brinfo string) (usertokeninfo, error) {
|
func (mg *Maingate) getUserTokenWithCheck(platform string, userid string, brinfo string) (usertokeninfo, error) {
|
||||||
@ -700,14 +811,19 @@ func (mg *Maingate) getProviderInfo(platform string, uid string) (string, string
|
|||||||
if provider == "" || providerid == "" {
|
if provider == "" || providerid == "" {
|
||||||
return "", "", errors.New("getProviderInfo - firebase info not found: " + provider + " / " + providerid)
|
return "", "", errors.New("getProviderInfo - firebase info not found: " + provider + " / " + providerid)
|
||||||
}
|
}
|
||||||
|
case "":
|
||||||
|
//guest auth
|
||||||
|
providerid = uid
|
||||||
|
if providerid == "" {
|
||||||
|
return "", "", errors.New("getProviderInfo - guest provider id not found: " + provider + " / " + providerid)
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
provider = platform
|
provider = platform
|
||||||
providerid = uid
|
providerid = uid
|
||||||
}
|
|
||||||
|
|
||||||
if provider == "" || providerid == "" {
|
if provider == "" || providerid == "" {
|
||||||
return "", "", errors.New("getProviderInfo - provider info not found: " + provider + " / " + providerid)
|
return "", "", errors.New("getProviderInfo - provider info not found: " + provider + " / " + providerid)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return provider, providerid, nil
|
return provider, providerid, nil
|
||||||
|
|
||||||
|
|||||||
@ -95,7 +95,7 @@ func (p *memberContainerPtr[K, T]) contains(key K, out *T) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if out != nil {
|
if out != nil {
|
||||||
out = &found
|
*out = found
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
506
core/service.go
506
core/service.go
@ -1,7 +1,6 @@
|
|||||||
package core
|
package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
@ -14,7 +13,6 @@ import (
|
|||||||
|
|
||||||
"repositories.action2quare.com/ayo/gocommon"
|
"repositories.action2quare.com/ayo/gocommon"
|
||||||
"repositories.action2quare.com/ayo/gocommon/logger"
|
"repositories.action2quare.com/ayo/gocommon/logger"
|
||||||
"repositories.action2quare.com/ayo/gocommon/session"
|
|
||||||
|
|
||||||
"go.mongodb.org/mongo-driver/bson"
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||||
@ -36,7 +34,7 @@ type blockinfoWithStringId struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type whitelistmember struct {
|
type whitelistmember struct {
|
||||||
Id primitive.ObjectID `bson:"_id" json:"_id"`
|
Id primitive.ObjectID `bson:"_id,omitempty" json:"_id,omitempty"`
|
||||||
Email string `bson:"email" json:"email"`
|
Email string `bson:"email" json:"email"`
|
||||||
Platform string `bson:"platform" json:"platform"`
|
Platform string `bson:"platform" json:"platform"`
|
||||||
Desc string `bson:"desc" json:"desc"`
|
Desc string `bson:"desc" json:"desc"`
|
||||||
@ -92,6 +90,7 @@ type Maintenance struct {
|
|||||||
type DivisionForUser struct {
|
type DivisionForUser struct {
|
||||||
Priority int `bson:"priority" json:"priority"`
|
Priority int `bson:"priority" json:"priority"`
|
||||||
State DivisionStateName `bson:"state" json:"state"`
|
State DivisionStateName `bson:"state" json:"state"`
|
||||||
|
LockCreateChar bool `bson:"lockcreatechar" json:"lockcreatechar"`
|
||||||
Maintenance *Maintenance `bson:"maintenance,omitempty" json:"maintenance,omitempty"`
|
Maintenance *Maintenance `bson:"maintenance,omitempty" json:"maintenance,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,7 +111,7 @@ type serviceDescription struct {
|
|||||||
MaximumNumLinkAccount int64
|
MaximumNumLinkAccount int64
|
||||||
VersionSplits map[string]string `bson:"version_splits" json:"version_splits"`
|
VersionSplits map[string]string `bson:"version_splits" json:"version_splits"`
|
||||||
|
|
||||||
sessionProvider session.Provider
|
auths *gocommon.AuthCollection
|
||||||
wl *memberContainerPtr[string, *whitelistmember]
|
wl *memberContainerPtr[string, *whitelistmember]
|
||||||
bl *memberContainerPtr[primitive.ObjectID, *blockinfo]
|
bl *memberContainerPtr[primitive.ObjectID, *blockinfo]
|
||||||
mongoClient gocommon.MongoClient
|
mongoClient gocommon.MongoClient
|
||||||
@ -163,7 +162,6 @@ func (sh *serviceDescription) readProfile(authtype string, id string, binfo stri
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(userinfo.token) == 0 {
|
if len(userinfo.token) == 0 {
|
||||||
return "", errors.New("refreshtoken token not found")
|
return "", errors.New("refreshtoken token not found")
|
||||||
}
|
}
|
||||||
@ -255,7 +253,7 @@ func (sh *serviceDescription) prepare(mg *Maingate) error {
|
|||||||
|
|
||||||
sh.MaximumNumLinkAccount = mg.maingateConfig.MaximumNumLinkAccount
|
sh.MaximumNumLinkAccount = mg.maingateConfig.MaximumNumLinkAccount
|
||||||
sh.mongoClient = mg.mongoClient
|
sh.mongoClient = mg.mongoClient
|
||||||
sh.sessionProvider = mg.sessionProvider
|
sh.auths = mg.auths
|
||||||
sh.sessionTTL = time.Duration(mg.SessionTTL * int64(time.Second))
|
sh.sessionTTL = time.Duration(mg.SessionTTL * int64(time.Second))
|
||||||
sh.serviceCodeBytes, _ = hex.DecodeString(sh.ServiceCode)
|
sh.serviceCodeBytes, _ = hex.DecodeString(sh.ServiceCode)
|
||||||
sh.getUserBrowserInfo = mg.GetUserBrowserInfo
|
sh.getUserBrowserInfo = mg.GetUserBrowserInfo
|
||||||
@ -294,10 +292,11 @@ func (sh *serviceDescription) link(w http.ResponseWriter, r *http.Request) {
|
|||||||
newType := queryvals.Get("ntype")
|
newType := queryvals.Get("ntype")
|
||||||
newId := queryvals.Get("nid")
|
newId := queryvals.Get("nid")
|
||||||
|
|
||||||
oldAuth, err := sh.sessionProvider.Query(sk)
|
oldAuth := sh.auths.Find(sk)
|
||||||
if err != nil {
|
if oldAuth == nil {
|
||||||
logger.Println("sessionProvider.Query return err :", err)
|
// 잘못된 세션
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
logger.Println("link failed. session key is not valid :", sk)
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -312,13 +311,6 @@ func (sh *serviceDescription) link(w http.ResponseWriter, r *http.Request) {
|
|||||||
// fmt.Println(oldAuth.Uid)
|
// fmt.Println(oldAuth.Uid)
|
||||||
// fmt.Println("=================")
|
// fmt.Println("=================")
|
||||||
|
|
||||||
//if oldAuth.Token != oldToken || oldAuth.Uid != oldId || oldAuth.Platform != oldType {
|
|
||||||
if oldAuth.Uid != oldId || oldAuth.Platform != oldType {
|
|
||||||
logger.Println("link failed. session key is not correct :", oldAuth, queryvals)
|
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
bfinfo, err := sh.getUserBrowserInfo(r)
|
bfinfo, err := sh.getUserBrowserInfo(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("getUserBrowserInfo failed :", err)
|
logger.Error("getUserBrowserInfo failed :", err)
|
||||||
@ -326,16 +318,35 @@ func (sh *serviceDescription) link(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
guestlink := (len(oldType) == 0)
|
||||||
|
if !guestlink {
|
||||||
_, err = sh.readProfile(oldType, oldId, bfinfo)
|
_, err = sh.readProfile(oldType, oldId, bfinfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("readProfile(old) failed :", err)
|
logger.Println("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.Println("getProviderInfo failed :", err)
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//if oldAuth.Token != oldToken || oldAuth.Uid != oldId || oldAuth.Platform != oldType {
|
||||||
|
if oldAuth.Uid != oldId || oldAuth.Platform != oldType {
|
||||||
|
logger.Println("link failed. session key is not correct :", *oldAuth, queryvals)
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
email, err := sh.readProfile(newType, newId, bfinfo)
|
email, err := sh.readProfile(newType, newId, bfinfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("readProfile(new) failed :", err)
|
logger.Println("readProfile(new) failed :", err)
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -348,8 +359,9 @@ func (sh *serviceDescription) link(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
newType, newId, err = sh.getProviderInfo(newType, newId)
|
newType, newId, err = sh.getProviderInfo(newType, newId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("getProviderInfo failed :", err)
|
logger.Println("getProviderInfo failed :", err)
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
createtime := primitive.NewDateTimeFromTime(time.Now().UTC())
|
createtime := primitive.NewDateTimeFromTime(time.Now().UTC())
|
||||||
@ -372,13 +384,13 @@ func (sh *serviceDescription) link(w http.ResponseWriter, r *http.Request) {
|
|||||||
"_id": link["_id"].(primitive.ObjectID),
|
"_id": link["_id"].(primitive.ObjectID),
|
||||||
}, bson.M{
|
}, bson.M{
|
||||||
"$setOnInsert": bson.M{
|
"$setOnInsert": bson.M{
|
||||||
"accid": oldAuth.Account,
|
"accid": oldAuth.Accid,
|
||||||
"create": createtime,
|
"create": createtime,
|
||||||
},
|
},
|
||||||
}, options.Update().SetUpsert(true))
|
}, options.Update().SetUpsert(true))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("link failed. Update ServiceName err :", err)
|
logger.Error("link failed. Update ServiceName err :", err)
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -390,6 +402,20 @@ func (sh *serviceDescription) link(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
logger.Println("link success :", r.URL.Query())
|
logger.Println("link success :", r.URL.Query())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -411,11 +437,13 @@ func (sh *serviceDescription) unlink(w http.ResponseWriter, r *http.Request) {
|
|||||||
sType := queryvals.Get("stype")
|
sType := queryvals.Get("stype")
|
||||||
sId := queryvals.Get("sid")
|
sId := queryvals.Get("sid")
|
||||||
sk := queryvals.Get("sk")
|
sk := queryvals.Get("sk")
|
||||||
|
targetType := queryvals.Get("ttype")
|
||||||
|
|
||||||
authInfo, err := sh.sessionProvider.Query(sk)
|
authInfo := sh.auths.Find(sk)
|
||||||
if err != nil {
|
if authInfo == nil {
|
||||||
logger.Println("sessionProvider.Query return err :", err)
|
// 잘못된 세션
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
logger.Println("linkinfo failed. session key is not valid :", sk)
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -427,55 +455,60 @@ func (sh *serviceDescription) unlink(w http.ResponseWriter, r *http.Request) {
|
|||||||
// fmt.Println(authInfo.Uid)
|
// fmt.Println(authInfo.Uid)
|
||||||
// fmt.Println("=================")
|
// fmt.Println("=================")
|
||||||
|
|
||||||
if authInfo.Uid != sId || authInfo.Platform != sType {
|
sType, sId, err := sh.getProviderInfo(sType, sId)
|
||||||
logger.Println("unlink failed. session key is not correct :", authInfo, queryvals)
|
if err != nil {
|
||||||
|
logger.Println("getProviderInfo failed :", err)
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
numRecord, err := sh.mongoClient.Collection(CollectionAccount).CountDocuments(context.Background(), bson.M{
|
if authInfo.Uid != sId || authInfo.Platform != sType {
|
||||||
"accid": authInfo.Account,
|
logger.Println("unlink failed. session key is not correct :", *authInfo, queryvals)
|
||||||
}, options.Count().SetLimit(2))
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
accDocs, err := sh.mongoClient.FindAll(CollectionAccount, bson.M{
|
||||||
|
"accid": authInfo.Accid,
|
||||||
|
}, options.Find().SetProjection(bson.M{
|
||||||
|
"_id": 1,
|
||||||
|
}))
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("unlink failed, fail to count accounts :", err)
|
logger.Error("unlink failed, fail to count accounts :", err)
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
|
|
||||||
if numRecord <= 1 {
|
if len(accDocs) <= 1 {
|
||||||
logger.Println("unlink failed. At least one link must be maintained. :", r.URL.Query())
|
logger.Println("unlink failed. At least one link must be maintained. :", r.URL.Query())
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
sType, sId, err = sh.getProviderInfo(sType, sId)
|
var ids primitive.A
|
||||||
if err != nil {
|
for _, accDoc := range accDocs {
|
||||||
logger.Error("getProviderInfo failed :", err)
|
ids = append(ids, accDoc["_id"].(primitive.ObjectID))
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
link, err := sh.mongoClient.FindOne(CollectionLink, bson.M{
|
link, err := sh.mongoClient.FindOneAndDelete(CollectionLink, bson.M{
|
||||||
"platform": sType,
|
"platform": targetType,
|
||||||
"uid": sId,
|
"_id": bson.M{"$in": ids},
|
||||||
}, options.FindOne().SetProjection(bson.M{"_id": 1}))
|
}, options.FindOneAndDelete().SetProjection(bson.M{"_id": 1}))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("link failed. FindOneAndUpdate link err:", err)
|
logger.Error("unlink failed. FindOneAndDelete link err:", err)
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
newid, err := sh.mongoClient.FindOneAndDelete(CollectionAccount, bson.M{
|
preid, err := sh.mongoClient.FindOneAndDelete(CollectionAccount, bson.M{
|
||||||
"_id": link["_id"].(primitive.ObjectID),
|
"_id": link["_id"].(primitive.ObjectID),
|
||||||
}, options.FindOneAndDelete().SetProjection(bson.M{"_id": 1}))
|
}, options.FindOneAndDelete().SetProjection(bson.M{"_id": 1}))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("unlink failed. Delete ServiceName err :", err)
|
logger.Error("unlink failed. Delete ServiceName err :", err)
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if preid == nil {
|
||||||
// newid가 있어야 한다. 그래야 기존 서비스 계정이 없는 상태이다.
|
|
||||||
if newid == nil {
|
|
||||||
// 이미 계정이 있네?
|
|
||||||
logger.Println("unlink failed. service account not found:", r.URL.Query())
|
logger.Println("unlink failed. service account not found:", r.URL.Query())
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
@ -503,10 +536,11 @@ func (sh *serviceDescription) linkinfo(w http.ResponseWriter, r *http.Request) {
|
|||||||
sId := queryvals.Get("sid")
|
sId := queryvals.Get("sid")
|
||||||
sk := queryvals.Get("sk")
|
sk := queryvals.Get("sk")
|
||||||
|
|
||||||
authInfo, err := sh.sessionProvider.Query(sk)
|
authInfo := sh.auths.Find(sk)
|
||||||
if err != nil {
|
if authInfo == nil {
|
||||||
logger.Println("sessionProvider.Query return err :", err)
|
// 잘못된 세션
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
logger.Println("linkinfo failed. session key is not valid :", sk)
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -518,25 +552,104 @@ func (sh *serviceDescription) linkinfo(w http.ResponseWriter, r *http.Request) {
|
|||||||
// fmt.Println(authInfo.Uid)
|
// fmt.Println(authInfo.Uid)
|
||||||
// fmt.Println("=================")
|
// fmt.Println("=================")
|
||||||
|
|
||||||
|
sType, sId, err := sh.getProviderInfo(sType, sId)
|
||||||
|
if err != nil {
|
||||||
|
logger.Println("getProviderInfo failed :", err)
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
//if oldAuth.Token != oldToken || oldAuth.Uid != oldId || oldAuth.Platform != oldType {
|
//if oldAuth.Token != oldToken || oldAuth.Uid != oldId || oldAuth.Platform != oldType {
|
||||||
if authInfo.Uid != sId || authInfo.Platform != sType {
|
if authInfo.Uid != sId || authInfo.Platform != sType {
|
||||||
logger.Println("linkinfo failed. session key is not correct :", authInfo, queryvals)
|
logger.Println("linkinfo failed. session key is not correct :", *authInfo, queryvals)
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
numRecord, err := sh.mongoClient.Collection(CollectionAccount).CountDocuments(context.Background(), bson.M{
|
platformName := "platform"
|
||||||
"accid": authInfo.Account,
|
accDocs, err := sh.mongoClient.FindAll(CollectionAccount, bson.M{
|
||||||
}, options.Count().SetLimit(sh.MaximumNumLinkAccount))
|
"accid": authInfo.Accid,
|
||||||
|
}, options.Find().SetLimit(sh.MaximumNumLinkAccount).SetProjection(bson.M{
|
||||||
|
"_id": 1,
|
||||||
|
}))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("linkinfo failed. CountDocuments err :", err)
|
logger.Error("linkinfo failed. CountDocuments err :", err)
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var ids primitive.A
|
||||||
|
for _, accDoc := range accDocs {
|
||||||
|
ids = append(ids, accDoc["_id"].(primitive.ObjectID))
|
||||||
|
}
|
||||||
|
|
||||||
|
links, err := sh.mongoClient.FindAll(CollectionLink, bson.M{
|
||||||
|
"_id": bson.M{"$in": ids},
|
||||||
|
}, options.Find().SetLimit(sh.MaximumNumLinkAccount).SetProjection(bson.M{
|
||||||
|
platformName: 1,
|
||||||
|
}))
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("linkinfo failed. FindAll returns err :", err)
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var linkstrs []string
|
||||||
|
for _, link := range links {
|
||||||
|
linkstrs = append(linkstrs, link[platformName].(string))
|
||||||
|
}
|
||||||
|
|
||||||
|
linkbytes, err := json.Marshal(linkstrs)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("linkinfo failed. json marshal fail :", err)
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Println("linkinfo :", linkstrs)
|
||||||
|
w.Write(linkbytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
// == 계정 이메일 조회
|
||||||
|
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)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Println("linkinfo :", numRecord)
|
queryvals := r.URL.Query()
|
||||||
w.Write([]byte(fmt.Sprintf(`{"num_linked_account":"%d"}`, numRecord)))
|
sk := queryvals.Get("sk")
|
||||||
|
|
||||||
|
authInfo := sh.auths.Find(sk)
|
||||||
|
if authInfo == nil {
|
||||||
|
logger.Println(" session key is not valid :", sk)
|
||||||
|
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)))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -556,26 +669,8 @@ func (sh *serviceDescription) authorize(w http.ResponseWriter, r *http.Request)
|
|||||||
queryvals := r.URL.Query()
|
queryvals := r.URL.Query()
|
||||||
authtype := queryvals.Get("type")
|
authtype := queryvals.Get("type")
|
||||||
uid := queryvals.Get("id")
|
uid := queryvals.Get("id")
|
||||||
if sk := queryvals.Get("sk"); len(sk) > 0 {
|
//accesstoken := queryvals.Get("token") //-- 이거 이제 받지마라
|
||||||
success, err := sh.sessionProvider.Touch(sk)
|
session := queryvals.Get("sk")
|
||||||
if err != nil {
|
|
||||||
logger.Error("authorize failed. sessionProvider.Touch err:", err)
|
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// !success일 때 빈 body를 보내면 클라이언트는 로그아웃 된다.
|
|
||||||
if success {
|
|
||||||
json.NewEncoder(w).Encode(map[string]any{
|
|
||||||
"sk": sk,
|
|
||||||
"expirein": sh.sessionTTL.Seconds(),
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
logger.Println("sh.sessionProvider.Touch failed :", sk)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var email string
|
var email string
|
||||||
|
|
||||||
if !*noauth {
|
if !*noauth {
|
||||||
@ -583,41 +678,39 @@ func (sh *serviceDescription) authorize(w http.ResponseWriter, r *http.Request)
|
|||||||
//email, err := sh.readProfile(authtype, uid, accesstoken)
|
//email, err := sh.readProfile(authtype, uid, accesstoken)
|
||||||
bfinfo, err := sh.getUserBrowserInfo(r)
|
bfinfo, err := sh.getUserBrowserInfo(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("getUserBrowserInfo failed :", err)
|
logger.Println("getUserBrowserInfo failed :", err)
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
email, err = sh.readProfile(authtype, uid, bfinfo)
|
email, err = sh.readProfile(authtype, uid, bfinfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("readProfile failed :", err)
|
logger.Println("readProfile failed :", err)
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
newType, newId, err := sh.getProviderInfo(authtype, uid)
|
newType, newId, err := sh.getProviderInfo(authtype, uid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("getProviderInfo failed :", err)
|
logger.Println("getProviderInfo failed :", err)
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if authtype != newType || uid != newId {
|
if authtype != newType || uid != newId {
|
||||||
|
logger.Printf("auth success ( redirect ) : %s->%s, %s->%s, %s, %s", authtype, newType, uid, newId, email, session)
|
||||||
authtype = newType
|
authtype = newType
|
||||||
uid = newId
|
uid = newId
|
||||||
}
|
}
|
||||||
} else if *devflag {
|
|
||||||
email = fmt.Sprintf("%s@guest.flag", uid)
|
|
||||||
} else {
|
} else {
|
||||||
// authtype이 없으면 입장 불가
|
email = fmt.Sprintf("%s@guest.flag", uid)
|
||||||
logger.Error("authorize failed. 'type' query parameter is missing")
|
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
email = fmt.Sprintf("%s@noauth.flag", uid)
|
email = fmt.Sprintf("%s@noauth.flag", uid)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//if len(session) == 0 && len(email) > 0 {
|
||||||
|
if len(session) == 0 {
|
||||||
// platform + id -> account id
|
// platform + id -> account id
|
||||||
createtime := primitive.NewDateTimeFromTime(time.Now().UTC())
|
createtime := primitive.NewDateTimeFromTime(time.Now().UTC())
|
||||||
link, err := sh.mongoClient.FindOneAndUpdate(CollectionLink, bson.M{
|
link, err := sh.mongoClient.FindOneAndUpdate(CollectionLink, bson.M{
|
||||||
@ -628,13 +721,15 @@ func (sh *serviceDescription) authorize(w http.ResponseWriter, r *http.Request)
|
|||||||
"create": createtime,
|
"create": createtime,
|
||||||
"email": email,
|
"email": email,
|
||||||
},
|
},
|
||||||
}, options.FindOneAndUpdate().SetReturnDocument(options.After).SetUpsert(true).SetProjection(bson.M{"_id": 1}))
|
}, options.FindOneAndUpdate().SetReturnDocument(options.After).SetUpsert(true).SetProjection(bson.M{
|
||||||
|
"_id": 1,
|
||||||
|
"_ts": 1,
|
||||||
|
}))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("authorize failed :", err)
|
logger.Error("authorize failed :", err)
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
linkid := link["_id"].(primitive.ObjectID)
|
linkid := link["_id"].(primitive.ObjectID)
|
||||||
newaccid := primitive.NewObjectID()
|
newaccid := primitive.NewObjectID()
|
||||||
for i := 0; i < len(sh.serviceCodeBytes); i++ {
|
for i := 0; i < len(sh.serviceCodeBytes); i++ {
|
||||||
@ -668,29 +763,110 @@ func (sh *serviceDescription) authorize(w http.ResponseWriter, r *http.Request)
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
sk, err := sh.sessionProvider.New(&session.Authorization{
|
newsession := primitive.NewObjectID()
|
||||||
Account: accid,
|
expired := primitive.NewDateTimeFromTime(time.Now().UTC().Add(sh.sessionTTL))
|
||||||
|
newauth := gocommon.Authinfo{
|
||||||
|
Accid: accid,
|
||||||
|
ServiceCode: sh.ServiceCode,
|
||||||
Platform: authtype,
|
Platform: authtype,
|
||||||
Uid: uid,
|
Uid: uid,
|
||||||
Email: email,
|
Email: email,
|
||||||
})
|
Sk: newsession,
|
||||||
|
Expired: expired,
|
||||||
|
//RefreshToken: queryvals.Get("rt"),
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _, err = sh.mongoClient.UpsertOne(CollectionAuth, bson.M{"_id": newauth.Accid}, &newauth)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("authorize failed. sessionProvider.New err:", err)
|
logger.Error("authorize failed :", err)
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logger.Println("session created :", accid, authtype, uid, email, newsession)
|
||||||
|
|
||||||
output := map[string]any{
|
output := map[string]any{
|
||||||
"sk": sk,
|
"sk": newsession.Hex(),
|
||||||
"expirein": sh.sessionTTL.Seconds(),
|
"expirein": sh.sessionTTL.Seconds(),
|
||||||
"newAccount": newaccount,
|
"newAccount": newaccount,
|
||||||
"accid": accid.Hex(),
|
"accid": newauth.Accid.Hex(),
|
||||||
}
|
}
|
||||||
if *noauth {
|
if *noauth {
|
||||||
output["noauth"] = true
|
output["noauth"] = true
|
||||||
}
|
}
|
||||||
|
|
||||||
json.NewEncoder(w).Encode(output)
|
if link["_ts"] != nil {
|
||||||
|
delts := link["_ts"].(primitive.DateTime)
|
||||||
|
if !delts.Time().IsZero() {
|
||||||
|
// 삭제된 계정. 삭제 되었다고 알려주자
|
||||||
|
w.Header().Add("MG-ACCOUNT-DELETED", "TRUE")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bt, _ := json.Marshal(output)
|
||||||
|
w.Write(bt)
|
||||||
|
} else if len(session) > 0 {
|
||||||
|
sessionobj, _ := primitive.ObjectIDFromHex(session)
|
||||||
|
if !sessionobj.IsZero() {
|
||||||
|
updated, _, err := sh.mongoClient.Update(CollectionAuth,
|
||||||
|
bson.M{
|
||||||
|
"sk": sessionobj,
|
||||||
|
},
|
||||||
|
bson.M{
|
||||||
|
"$currentDate": bson.M{
|
||||||
|
"_ts": bson.M{"$type": "date"},
|
||||||
|
},
|
||||||
|
}, options.Update().SetUpsert(false))
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("update auth collection failed :", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !updated {
|
||||||
|
// 세션이 없네?
|
||||||
|
logger.Println("authorize failed. session not exists in database :", session)
|
||||||
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
output := map[string]any{
|
||||||
|
"sk": session,
|
||||||
|
"expirein": sh.sessionTTL.Seconds(),
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Println("session updated :", authtype, uid, session)
|
||||||
|
|
||||||
|
authInfo := sh.auths.Find(session)
|
||||||
|
if authInfo == nil {
|
||||||
|
// 잘못된 세션
|
||||||
|
logger.Println("authorize failed. fail to find authInfo :", session)
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//혹시 삭제 된 계정 아닌지 확인해본다.
|
||||||
|
link, err := sh.mongoClient.FindOne(CollectionLink, bson.M{
|
||||||
|
"platform": authtype,
|
||||||
|
"uid": uid,
|
||||||
|
}, options.FindOne().SetProjection(bson.M{
|
||||||
|
"_ts": 1,
|
||||||
|
}))
|
||||||
|
if link["_ts"] != nil {
|
||||||
|
delts := link["_ts"].(primitive.DateTime)
|
||||||
|
if !delts.Time().IsZero() {
|
||||||
|
// 삭제된 계정. 삭제 되었다고 알려주자
|
||||||
|
w.Header().Add("MG-ACCOUNT-DELETED", "TRUE")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bt, _ := json.Marshal(output)
|
||||||
|
w.Write(bt)
|
||||||
|
} else {
|
||||||
|
logger.Println("authorize failed. sk is not valid hex :", session)
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logger.Println("authorize failed. id empty :", queryvals)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sh *serviceDescription) findVersionSplit(version string) []byte {
|
func (sh *serviceDescription) findVersionSplit(version string) []byte {
|
||||||
@ -706,6 +882,109 @@ func (sh *serviceDescription) findVersionSplit(version string) []byte {
|
|||||||
return sh.divisionsSplits["default"]
|
return sh.divisionsSplits["default"]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 := sh.auths.Find(sk)
|
||||||
|
if authInfo == nil {
|
||||||
|
// 잘못된 세션
|
||||||
|
logger.Println("delacc failed. session key is not valid :", sk)
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
originAuthType := sType
|
||||||
|
sType, sId, err := sh.getProviderInfo(sType, sId)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("delacc failed. getProviderInfo err :", err)
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
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.Accid,
|
||||||
|
}, 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 := primitive.NewDateTimeFromTime(time.Now().UTC())
|
||||||
|
delop = primitive.M{
|
||||||
|
"$set": primitive.M{"_ts": curtime},
|
||||||
|
}
|
||||||
|
|
||||||
|
if originAuthType == AuthPlatformFirebaseAuth {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
func (sh *serviceDescription) serveHTTP(w http.ResponseWriter, r *http.Request) {
|
func (sh *serviceDescription) serveHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
defer func() {
|
defer func() {
|
||||||
s := recover()
|
s := recover()
|
||||||
@ -727,6 +1006,10 @@ func (sh *serviceDescription) serveHTTP(w http.ResponseWriter, r *http.Request)
|
|||||||
sh.unlink(w, r)
|
sh.unlink(w, r)
|
||||||
} else if strings.HasSuffix(r.URL.Path, "/linkinfo") {
|
} else if strings.HasSuffix(r.URL.Path, "/linkinfo") {
|
||||||
sh.linkinfo(w, r)
|
sh.linkinfo(w, r)
|
||||||
|
} else if strings.HasSuffix(r.URL.Path, "/emailinfo") {
|
||||||
|
sh.emailinfo(w, r)
|
||||||
|
} else if strings.HasSuffix(r.URL.Path, "/delacc") {
|
||||||
|
sh.delacc(w, r)
|
||||||
} else if strings.HasSuffix(r.URL.Path, "/divs") {
|
} else if strings.HasSuffix(r.URL.Path, "/divs") {
|
||||||
// TODO : 세션키와 authtoken을 헤더로 받아서 accid 조회
|
// TODO : 세션키와 authtoken을 헤더로 받아서 accid 조회
|
||||||
queryvals := r.URL.Query()
|
queryvals := r.URL.Query()
|
||||||
@ -741,14 +1024,7 @@ func (sh *serviceDescription) serveHTTP(w http.ResponseWriter, r *http.Request)
|
|||||||
// TODO : 각 서버에 있는 자산? 캐릭터 정보를 보여줘야 하나. 뭘 보여줄지는 프로젝트에 문의
|
// TODO : 각 서버에 있는 자산? 캐릭터 정보를 보여줘야 하나. 뭘 보여줄지는 프로젝트에 문의
|
||||||
// 일단 서버 종류만 내려보내자
|
// 일단 서버 종류만 내려보내자
|
||||||
// 세션키가 있는지 확인
|
// 세션키가 있는지 확인
|
||||||
authInfo, err := sh.sessionProvider.Query(sk)
|
if _, ok := sh.auths.IsValid(sk, ""); !ok {
|
||||||
if err != nil {
|
|
||||||
logger.Println("sessionProvider.Query return err :", err)
|
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if authInfo.Account.IsZero() {
|
|
||||||
logger.Println("sessionkey is not valid :", sk)
|
logger.Println("sessionkey is not valid :", sk)
|
||||||
w.WriteHeader(http.StatusUnauthorized)
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
return
|
return
|
||||||
@ -769,14 +1045,7 @@ func (sh *serviceDescription) serveHTTP(w http.ResponseWriter, r *http.Request)
|
|||||||
// TODO : 각 서버에 있는 자산? 캐릭터 정보를 보여줘야 하나. 뭘 보여줄지는 프로젝트에 문의
|
// TODO : 각 서버에 있는 자산? 캐릭터 정보를 보여줘야 하나. 뭘 보여줄지는 프로젝트에 문의
|
||||||
// 일단 서버 종류만 내려보내자
|
// 일단 서버 종류만 내려보내자
|
||||||
// 세션키가 있는지 확인
|
// 세션키가 있는지 확인
|
||||||
authInfo, err := sh.sessionProvider.Query(sk)
|
if _, ok := sh.auths.IsValid(sk, ""); !ok {
|
||||||
if err != nil {
|
|
||||||
logger.Println("sessionProvider.Query return err :", err)
|
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if authInfo.Account.IsZero() {
|
|
||||||
logger.Println("sessionkey is not valid :", sk)
|
logger.Println("sessionkey is not valid :", sk)
|
||||||
w.WriteHeader(http.StatusUnauthorized)
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
return
|
return
|
||||||
@ -792,14 +1061,13 @@ func (sh *serviceDescription) serveHTTP(w http.ResponseWriter, r *http.Request)
|
|||||||
|
|
||||||
case DivisionState_RestrictedOpen:
|
case DivisionState_RestrictedOpen:
|
||||||
// 점검중이면 whitelist만 입장 가능
|
// 점검중이면 whitelist만 입장 가능
|
||||||
authInfo, err := sh.sessionProvider.Query(sk)
|
cell := sh.auths.QuerySession(sk, "")
|
||||||
if err != nil {
|
if cell == nil {
|
||||||
logger.Println("sessionProvider.Query return err :", err)
|
logger.Println("sessionkey is not valid :", sk)
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
wm := &whitelistmember{Email: cell.ToAuthinfo().Email, Platform: cell.ToAuthinfo().Platform}
|
||||||
wm := &whitelistmember{Email: authInfo.Email, Platform: authInfo.Platform}
|
|
||||||
if sh.wl.contains(wm.Key(), nil) {
|
if sh.wl.contains(wm.Key(), nil) {
|
||||||
// qa 권한이면 입장 가능
|
// qa 권한이면 입장 가능
|
||||||
w.Write([]byte(fmt.Sprintf(`{"service":"%s"}`, div.Url)))
|
w.Write([]byte(fmt.Sprintf(`{"service":"%s"}`, div.Url)))
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"repositories.action2quare.com/ayo/gocommon"
|
||||||
"repositories.action2quare.com/ayo/gocommon/logger"
|
"repositories.action2quare.com/ayo/gocommon/logger"
|
||||||
|
|
||||||
"go.mongodb.org/mongo-driver/bson"
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
@ -18,6 +19,14 @@ import (
|
|||||||
"go.mongodb.org/mongo-driver/mongo/options"
|
"go.mongodb.org/mongo-driver/mongo/options"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type authPipelineDocument struct {
|
||||||
|
OperationType string `bson:"operationType"`
|
||||||
|
DocumentKey struct {
|
||||||
|
Id primitive.ObjectID `bson:"_id"`
|
||||||
|
} `bson:"documentKey"`
|
||||||
|
Authinfo *gocommon.Authinfo `bson:"fullDocument"`
|
||||||
|
}
|
||||||
|
|
||||||
type servicePipelineDocument struct {
|
type servicePipelineDocument struct {
|
||||||
OperationType string `bson:"operationType"`
|
OperationType string `bson:"operationType"`
|
||||||
DocumentKey struct {
|
DocumentKey struct {
|
||||||
@ -213,3 +222,87 @@ func (mg *Maingate) watchServiceCollection(parentctx context.Context, serveMux *
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func watchAuthCollection(parentctx context.Context, ac *gocommon.AuthCollection, mongoClient gocommon.MongoClient) {
|
||||||
|
defer func() {
|
||||||
|
s := recover()
|
||||||
|
if s != nil {
|
||||||
|
logger.Error(s)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
matchStage := bson.D{
|
||||||
|
{
|
||||||
|
Key: "$match", Value: bson.D{
|
||||||
|
{Key: "operationType", Value: bson.D{
|
||||||
|
{Key: "$in", Value: bson.A{
|
||||||
|
"delete",
|
||||||
|
"insert",
|
||||||
|
"update",
|
||||||
|
}},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
projectStage := bson.D{
|
||||||
|
{
|
||||||
|
Key: "$project", Value: bson.D{
|
||||||
|
{Key: "documentKey", Value: 1},
|
||||||
|
{Key: "operationType", Value: 1},
|
||||||
|
{Key: "fullDocument", Value: 1},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var stream *mongo.ChangeStream
|
||||||
|
var err error
|
||||||
|
var ctx context.Context
|
||||||
|
|
||||||
|
for {
|
||||||
|
if stream == nil {
|
||||||
|
stream, err = mongoClient.Watch(CollectionAuth, mongo.Pipeline{matchStage, projectStage})
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("watchAuthCollection watch failed :", err)
|
||||||
|
time.Sleep(time.Minute)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ctx = context.TODO()
|
||||||
|
}
|
||||||
|
|
||||||
|
changed := stream.TryNext(ctx)
|
||||||
|
if ctx.Err() != nil {
|
||||||
|
logger.Error("watchAuthCollection stream.TryNext failed. process should be restarted! :", ctx.Err().Error())
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if changed {
|
||||||
|
var data authPipelineDocument
|
||||||
|
if err := stream.Decode(&data); err == nil {
|
||||||
|
ot := data.OperationType
|
||||||
|
switch ot {
|
||||||
|
case "insert":
|
||||||
|
ac.AddRaw(&mongoAuthCell{src: data.Authinfo})
|
||||||
|
case "update":
|
||||||
|
ac.AddRaw(&mongoAuthCell{src: data.Authinfo})
|
||||||
|
case "delete":
|
||||||
|
ac.RemoveByAccId(data.DocumentKey.Id)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logger.Error("watchAuthCollection stream.Decode failed :", err)
|
||||||
|
}
|
||||||
|
} else if stream.Err() != nil || stream.ID() == 0 {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
logger.Println("watchAuthCollection is done")
|
||||||
|
stream.Close(ctx)
|
||||||
|
return
|
||||||
|
|
||||||
|
case <-time.After(time.Second):
|
||||||
|
logger.Error("watchAuthCollection stream error :", stream.Err())
|
||||||
|
stream.Close(ctx)
|
||||||
|
stream = nil
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
6
go.mod
6
go.mod
@ -1,13 +1,13 @@
|
|||||||
module repositories.action2quare.com/ayo/maingate
|
module repositories.action2quare.com/ayo/maingate
|
||||||
|
|
||||||
go 1.19
|
go 1.18
|
||||||
|
|
||||||
require (
|
require (
|
||||||
firebase.google.com/go v3.13.0+incompatible
|
firebase.google.com/go v3.13.0+incompatible
|
||||||
github.com/golang-jwt/jwt v3.2.2+incompatible
|
github.com/golang-jwt/jwt v3.2.2+incompatible
|
||||||
go.mongodb.org/mongo-driver v1.11.7
|
go.mongodb.org/mongo-driver v1.11.7
|
||||||
google.golang.org/api v0.128.0
|
google.golang.org/api v0.128.0
|
||||||
repositories.action2quare.com/ayo/gocommon v0.0.0-20231128132952-e5a5240f96d8
|
repositories.action2quare.com/ayo/gocommon v0.0.0-20240205060841-c31f838ba8a9
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
@ -53,3 +53,5 @@ require (
|
|||||||
google.golang.org/grpc v1.56.0 // indirect
|
google.golang.org/grpc v1.56.0 // indirect
|
||||||
google.golang.org/protobuf v1.30.0 // indirect
|
google.golang.org/protobuf v1.30.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
|
replace repositories.action2quare.com/ayo/maingate => ./
|
||||||
|
|||||||
6
go.sum
6
go.sum
@ -268,5 +268,7 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
|||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
repositories.action2quare.com/ayo/gocommon v0.0.0-20231128132952-e5a5240f96d8 h1:GbvfiscAV/gquGzC9bJ3RTNtezLcdfGOv+9JmAZYQVc=
|
repositories.action2quare.com/ayo/gocommon v0.0.0-20230912075917-f9a146321cdb h1:Rdf6uhBIWunRLZ2LIT1hSovYXxZoOzx9mdSK5bjWpos=
|
||||||
repositories.action2quare.com/ayo/gocommon v0.0.0-20231128132952-e5a5240f96d8/go.mod h1:XvklTTSvQX5uviivGBcZo8eIL+mV94W2e4uBBXcT5JY=
|
repositories.action2quare.com/ayo/gocommon v0.0.0-20230912075917-f9a146321cdb/go.mod h1:rn6NA28Mej+qgLNx/Bu2wsdGyIycmacqlNP6gUXX2a0=
|
||||||
|
repositories.action2quare.com/ayo/gocommon v0.0.0-20240205060841-c31f838ba8a9 h1:5cQ60XjlI7k0qld0rIpd6gy7+a9csv3ijz1EVKTzsy8=
|
||||||
|
repositories.action2quare.com/ayo/gocommon v0.0.0-20240205060841-c31f838ba8a9/go.mod h1:rn6NA28Mej+qgLNx/Bu2wsdGyIycmacqlNP6gUXX2a0=
|
||||||
|
|||||||
15
main.go
15
main.go
@ -2,7 +2,9 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"math/rand"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
"repositories.action2quare.com/ayo/gocommon"
|
"repositories.action2quare.com/ayo/gocommon"
|
||||||
"repositories.action2quare.com/ayo/gocommon/flagx"
|
"repositories.action2quare.com/ayo/gocommon/flagx"
|
||||||
@ -19,29 +21,26 @@ func main() {
|
|||||||
flagx.Parse()
|
flagx.Parse()
|
||||||
|
|
||||||
logger.Println("build revision =", revision)
|
logger.Println("build revision =", revision)
|
||||||
|
rand.Seed(time.Now().UnixNano())
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
mg, err := core.New(ctx)
|
mg, err := core.New(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("core.New failed :", err)
|
logger.Error("core.New failed :", err)
|
||||||
return
|
panic(err)
|
||||||
}
|
}
|
||||||
defer mg.Destructor()
|
|
||||||
|
|
||||||
serveMux := http.NewServeMux()
|
serveMux := http.NewServeMux()
|
||||||
if err := mg.RegisterHandlers(ctx, serveMux, *prefix); err != nil {
|
if err := mg.RegisterHandlers(ctx, serveMux, *prefix); err != nil {
|
||||||
logger.Error("RegisterHandlers failed :", err)
|
logger.Error("RegisterHandlers failed :", err)
|
||||||
return
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
server := gocommon.NewHTTPServer(serveMux)
|
server := gocommon.NewHTTPServer(serveMux)
|
||||||
logger.Println("maingate is started")
|
logger.Println("maingate is started")
|
||||||
|
|
||||||
if err := server.Start(); err != nil {
|
if err := server.Start(); err != nil {
|
||||||
logger.Error("maingate is stopped with error :", err)
|
logger.Error("maingate is stopped with error :", err)
|
||||||
}
|
}
|
||||||
|
cancel()
|
||||||
logger.Println("maingate is terminated")
|
mg.Destructor()
|
||||||
}
|
}
|
||||||
|
|||||||
14
make_maingate_package.ps1
Normal file
14
make_maingate_package.ps1
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
# $ErrorActionPreference = 'SilentlyContinue'
|
||||||
|
|
||||||
|
$CurBranch = git branch --show-current
|
||||||
|
|
||||||
|
Remove-Item maingate.zip -Force -Recurse -ErrorAction SilentlyContinue
|
||||||
|
|
||||||
|
$Env:GOOS="linux"
|
||||||
|
$Env:GOARCH="amd64"
|
||||||
|
go build -ldflags="-s -w" .
|
||||||
|
|
||||||
|
Compress-Archive -Path maingate -Update -DestinationPath maingate.zip
|
||||||
|
Compress-Archive -Path *-firebase-*.json -Update -DestinationPath maingate.zip
|
||||||
|
Compress-Archive -Path fba -Update -DestinationPath maingate.zip
|
||||||
|
Compress-Archive -Path template -Update -DestinationPath maingate.zip
|
||||||
Reference in New Issue
Block a user