14 Commits

Author SHA1 Message Date
2d060fe117 [이민권] 쿠폰
- 유효번호 쿠폰 사용 안 되는 이슈 수정
- 유효번호 쿠폰이 사용 불가여도 사용 처리 되는 이슈 수정
2024-02-26 15:51:49 +09:00
231b1a35d5 Revert "[이민우] 운영툴 개선"
This reverts commit 424c8be420.
2024-02-22 17:07:16 +09:00
845784d204 api token 체크 누락 수정 2024-02-21 11:12:25 +09:00
424c8be420 [이민우] 운영툴 개선
- 쿠폰 사용 시 accid 변수타입 잘못 받는 이슈 수정
2024-02-20 11:23:27 +09:00
ce39e8d878 [이민권] go-common 최신화 2024-02-05 18:07:32 +09:00
54c727117b Revert "[이민권] go common 업데이트"
This reverts commit 7816fd56c0.
2024-01-25 17:12:41 +09:00
7816fd56c0 [이민권] go common 업데이트 2024-01-25 17:12:03 +09:00
564a2ee14a [이민권] 계정 삭제
- 버그 수정
2024-01-25 17:08:51 +09:00
cbcae00c77 [이민권] 계정 삭제
- 버그 수정
2024-01-25 16:18:38 +09:00
28dc84769d [이민우] 운영툴 개선
- 쿠폰 만료시간 못가져오는 이슈 수정
2024-01-22 17:43:53 +09:00
0c678947cd [이민우] 운영툴 개선
- 쿠폰 만료시간 안되는 이슈 수정
- 전체 유저 제재 목록을 볼 수 있도록 수정
2024-01-22 11:37:07 +09:00
dbd0a7bf5f [이민우] 운영툴 개선
- 쿠폰 삭제 기능 추가
- 쿠폰 만료 날짜 추가
- 무한인지 일회용인지 판별하여 쿠폰 사용 유무 검사
2024-01-19 14:24:52 +09:00
86247e053d 계정 이메일 조회 기능 추가
-> kd브렌치에 맞춰서 오류난 부분 수정
2024-01-16 12:13:20 +09:00
757c6d312c 계정 이메일 조회 기능 추가
Cherrypick - e7b3f59dd0
2024-01-16 11:47:26 +09:00
6 changed files with 172 additions and 57 deletions

View File

@ -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") json.NewEncoder(w).Encode(mg.bl.all())
if ok {
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)
@ -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
} }
@ -461,34 +459,52 @@ 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 {
authheader := r.Header.Get("Authorization") apiToken := r.Header.Get("MG-X-API-TOKEN")
if len(authheader) == 0 { if len(apiToken) > 0 {
logger.Println("Authorization header is not valid :", authheader) if apiToken != mg.maingateConfig.ApiToken {
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusUnauthorized)
return return
} }
req, _ := http.NewRequest("GET", "https://graph.microsoft.com/oidc/userinfo", nil) obj, err := primitive.ObjectIDFromHex(apiToken)
req.Header.Add("Authorization", authheader) if err != nil {
client := &http.Client{} logger.Error(err)
w.WriteHeader(http.StatusBadRequest)
return
}
resp, err := client.Do(req) apiTokenObj = obj
if err != nil { } else {
logger.Println("graph microsoft api call failed :", err) authheader := r.Header.Get("Authorization")
w.WriteHeader(http.StatusBadRequest) if len(authheader) == 0 {
return logger.Println("Authorization header is not valid :", authheader)
} w.WriteHeader(http.StatusUnauthorized)
defer resp.Body.Close() return
}
raw, _ := io.ReadAll(resp.Body) req, _ := http.NewRequest("GET", "https://graph.microsoft.com/oidc/userinfo", nil)
if err = json.Unmarshal(raw, &userinfo); err != nil { req.Header.Add("Authorization", authheader)
return client := &http.Client{}
}
if _, expired := userinfo["error"]; expired { resp, err := client.Do(req)
w.WriteHeader(http.StatusUnauthorized) if err != nil {
return logger.Println("graph microsoft api call failed :", err)
w.WriteHeader(http.StatusBadRequest)
return
}
defer resp.Body.Close()
raw, _ := io.ReadAll(resp.Body)
if err = json.Unmarshal(raw, &userinfo); err != nil {
return
}
if _, expired := userinfo["error"]; expired {
w.WriteHeader(http.StatusUnauthorized)
return
}
} }
} }
@ -504,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,

View File

@ -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 {
@ -72,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")
@ -92,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)
@ -154,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))
} }
@ -198,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)
@ -231,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
@ -275,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,
}) })
@ -286,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
@ -298,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
@ -310,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},
}) })
@ -328,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)
@ -370,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
}
}

View File

@ -123,6 +123,7 @@ func makeAuthCollection(mongoClient gocommon.MongoClient, sessionTTL time.Durati
type maingateConfig struct { 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"`
ApiToken string `json:"maingate_api_token"`
Autologin_ttl int64 `json:"autologin_ttl"` Autologin_ttl int64 `json:"autologin_ttl"`
AccDelTTL int64 `json:"acc_del_ttl"` AccDelTTL int64 `json:"acc_del_ttl"`
MaximumNumLinkAccount int64 `json:"maximum_num_link_account"` MaximumNumLinkAccount int64 `json:"maximum_num_link_account"`

View File

@ -610,6 +610,49 @@ func (sh *serviceDescription) linkinfo(w http.ResponseWriter, r *http.Request) {
w.Write(linkbytes) 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)
return
}
queryvals := r.URL.Query()
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)))
}
func (sh *serviceDescription) authorize(w http.ResponseWriter, r *http.Request) { func (sh *serviceDescription) authorize(w http.ResponseWriter, r *http.Request) {
defer func() { defer func() {
s := recover() s := recover()
@ -792,6 +835,28 @@ func (sh *serviceDescription) authorize(w http.ResponseWriter, r *http.Request)
logger.Println("session updated :", authtype, uid, session) 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) bt, _ := json.Marshal(output)
w.Write(bt) w.Write(bt)
} else { } else {
@ -844,6 +909,14 @@ func (sh *serviceDescription) delacc(w http.ResponseWriter, r *http.Request) {
return 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 { if authInfo.Uid != sId || authInfo.Platform != sType {
logger.Println("delacc failed. session key is not correct :", *authInfo, queryvals) logger.Println("delacc failed. session key is not correct :", *authInfo, queryvals)
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
@ -874,7 +947,7 @@ func (sh *serviceDescription) delacc(w http.ResponseWriter, r *http.Request) {
"$set": primitive.M{"_ts": curtime}, "$set": primitive.M{"_ts": curtime},
} }
if sType == AuthPlatformFirebaseAuth { if originAuthType == AuthPlatformFirebaseAuth {
sh.mongoClient.Delete(CollectionFirebaseUserInfo, bson.M{ sh.mongoClient.Delete(CollectionFirebaseUserInfo, bson.M{
"firebaseuserid": sId, "firebaseuserid": sId,
}) })
@ -933,6 +1006,8 @@ 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") { } else if strings.HasSuffix(r.URL.Path, "/delacc") {
sh.delacc(w, r) sh.delacc(w, r)
} else if strings.HasSuffix(r.URL.Path, "/divs") { } else if strings.HasSuffix(r.URL.Path, "/divs") {

2
go.mod
View File

@ -7,7 +7,7 @@ require (
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-20230912075917-f9a146321cdb repositories.action2quare.com/ayo/gocommon v0.0.0-20240205060841-c31f838ba8a9
) )
require ( require (

2
go.sum
View File

@ -270,3 +270,5 @@ honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWh
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-20230912075917-f9a146321cdb h1:Rdf6uhBIWunRLZ2LIT1hSovYXxZoOzx9mdSK5bjWpos= repositories.action2quare.com/ayo/gocommon v0.0.0-20230912075917-f9a146321cdb h1:Rdf6uhBIWunRLZ2LIT1hSovYXxZoOzx9mdSK5bjWpos=
repositories.action2quare.com/ayo/gocommon v0.0.0-20230912075917-f9a146321cdb/go.mod h1:rn6NA28Mej+qgLNx/Bu2wsdGyIycmacqlNP6gUXX2a0= 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=