Merge branch 'master' into kd-live

This commit is contained in:
2023-08-29 18:41:22 +09:00
10 changed files with 796 additions and 272 deletions

View File

@ -7,10 +7,9 @@ import (
"fmt"
"io"
"net/http"
"strconv"
"strings"
"sync/atomic"
"time"
"unsafe"
"repositories.action2quare.com/ayo/gocommon"
"repositories.action2quare.com/ayo/gocommon/logger"
@ -22,19 +21,45 @@ import (
type blockinfo struct {
Start primitive.DateTime `bson:"start" json:"start"`
End primitive.DateTime `bson:"_ts"`
End primitive.DateTime `bson:"_ts" json:"_ts"`
Reason string `bson:"reason" json:"reason"`
Accid primitive.ObjectID `bson:"_id,omitempty" json:"_id,omitempty"`
}
type blockinfoWithStringId struct {
Reason string `bson:"reason" json:"reason"`
StrId string `bson:"id" json:"id"`
StartUnix int64 `bson:"start_unix" json:"start_unix"`
EndUnix int64 `bson:"end_unix" json:"end_unix"`
}
type whitelistmember struct {
Email string `bson:"email" json:"email"`
Platform string `bson:"platform" json:"platform"`
Desc string `bson:"desc" json:"desc"`
Expired primitive.DateTime `bson:"_ts,omitempty" json:"_ts,omitempty"`
Id primitive.ObjectID `bson:"_id" json:"_id"`
Email string `bson:"email" json:"email"`
Platform string `bson:"platform" json:"platform"`
Desc string `bson:"desc" json:"desc"`
ExpiredAt primitive.DateTime `bson:"_ts,omitempty" json:"_ts,omitempty"`
}
type whitelist struct {
emailptr unsafe.Pointer
func (wh *whitelistmember) Key() string {
if strings.HasPrefix(wh.Email, "*@") {
// 도메인 전체 허용
return wh.Email[2:]
}
return wh.Email
}
func (wh *whitelistmember) Expired() bool {
// 얘는 Expired가 있기만 하면 제거된 상태
return wh.ExpiredAt != 0
}
func (bi *blockinfo) Key() primitive.ObjectID {
return bi.Accid
}
func (bi *blockinfo) Expired() bool {
return bi.End.Time().Unix() < time.Now().UTC().Unix()
}
type usertokeninfo struct {
@ -47,54 +72,6 @@ type usertokeninfo struct {
accesstoken_expire_time int64 // microsoft only
}
func (wl *whitelist) init(total []whitelistmember) {
all := make(map[string]*whitelistmember)
for _, member := range total {
all[whitelistKey(member.Email, member.Platform)] = &member
}
atomic.StorePointer(&wl.emailptr, unsafe.Pointer(&all))
}
func addToUnsafePointer(to *unsafe.Pointer, m *whitelistmember) {
ptr := atomic.LoadPointer(to)
src := (*map[string]*whitelistmember)(ptr)
next := map[string]*whitelistmember{}
for k, v := range *src {
next[k] = v
}
next[whitelistKey(m.Email, m.Platform)] = m
atomic.StorePointer(to, unsafe.Pointer(&next))
}
func removeFromUnsafePointer(from *unsafe.Pointer, email string, platform string) {
ptr := atomic.LoadPointer(from)
src := (*map[string]*whitelistmember)(ptr)
next := make(map[string]*whitelistmember)
for k, v := range *src {
next[k] = v
}
delete(next, whitelistKey(email, platform))
atomic.StorePointer(from, unsafe.Pointer(&next))
}
func (wl *whitelist) add(m *whitelistmember) {
addToUnsafePointer(&wl.emailptr, m)
}
func (wl *whitelist) remove(email string, platform string) {
removeFromUnsafePointer(&wl.emailptr, email, platform)
}
func (wl *whitelist) isMember(email string, platform string) bool {
ptr := atomic.LoadPointer(&wl.emailptr)
src := *(*map[string]*whitelistmember)(ptr)
_, exists := src[whitelistKey(email, platform)]
return exists
}
type DivisionStateName string
const (
@ -134,7 +111,8 @@ type serviceDescription struct {
VersionSplits map[string]string `bson:"version_splits" json:"version_splits"`
auths *gocommon.AuthCollection
wl *whitelist
wl memberContainerPtr[string, *whitelistmember]
bl memberContainerPtr[primitive.ObjectID, *blockinfo]
mongoClient gocommon.MongoClient
sessionTTL time.Duration
@ -280,10 +258,12 @@ func (sh *serviceDescription) prepare(mg *Maingate) error {
sh.updateUserinfo = mg.updateUserinfo
sh.getProviderInfo = mg.getProviderInfo
sh.wl = &mg.wl
sh.wl = mg.wl
sh.bl = mg.bl
sh.serviceSummarySerialized, _ = json.Marshal(sh.ServiceDescriptionSummary)
sh.serviceSerialized, _ = json.Marshal(sh)
logger.Println("service is ready :", sh.ServiceCode, string(sh.divisionsSerialized))
logger.Println("service is ready :", sh.ServiceCode, string(sh.serviceSerialized))
return nil
}
@ -721,28 +701,16 @@ func (sh *serviceDescription) authorize(w http.ResponseWriter, r *http.Request)
oldcreate := account["create"].(primitive.DateTime)
newaccount := oldcreate == createtime
var bi blockinfo
if err := sh.mongoClient.FindOneAs(CollectionBlock, bson.M{
"code": sh.ServiceCode,
"accid": accid,
}, &bi); err != nil {
logger.Error("authorize failed. find blockinfo in CollectionBlock err:", err)
w.WriteHeader(http.StatusInternalServerError)
var bi *blockinfo
if sh.bl.contains(accid, &bi) {
// 블럭된 계정. 블락 정보를 알려준다.
w.Header().Add("MG-ACCOUNTBLOCK-START", strconv.FormatInt(bi.Start.Time().Unix(), 10))
w.Header().Add("MG-ACCOUNTBLOCK-END", strconv.FormatInt(bi.End.Time().Unix(), 10))
w.Header().Add("MG-ACCOUNTBLOCK-REASON", bi.Reason)
w.WriteHeader(http.StatusUnauthorized)
return
}
if !bi.Start.Time().IsZero() {
now := time.Now().UTC()
if bi.Start.Time().Before(now) && bi.End.Time().After(now) {
// block됐네?
// status는 정상이고 reason을 넘겨주자
json.NewEncoder(w).Encode(map[string]any{
"blocked": bi,
})
return
}
}
newsession := primitive.NewObjectID()
expired := primitive.NewDateTimeFromTime(time.Now().UTC().Add(sh.sessionTTL))
newauth := gocommon.Authinfo{
@ -769,6 +737,9 @@ func (sh *serviceDescription) authorize(w http.ResponseWriter, r *http.Request)
"newAccount": newaccount,
"accid": newauth.Accid.Hex(),
}
if *noauth {
output["noauth"] = true
}
bt, _ := json.Marshal(output)
w.Write(bt)
} else if len(session) > 0 {
@ -971,7 +942,8 @@ func (sh *serviceDescription) serveHTTP(w http.ResponseWriter, r *http.Request)
w.WriteHeader(http.StatusBadRequest)
return
}
if sh.wl.isMember(cell.ToAuthinfo().Email, cell.ToAuthinfo().Platform) {
wm := &whitelistmember{Email: cell.ToAuthinfo().Email, Platform: cell.ToAuthinfo().Platform}
if sh.wl.contains(wm.Key(), nil) {
// qa 권한이면 입장 가능
w.Write([]byte(fmt.Sprintf(`{"service":"%s"}`, div.Url)))
} else if div.Maintenance != nil {