Compare commits

..

1 Commits

Author SHA1 Message Date
c64991ca61 live용 설정 추가 2023-06-21 18:15:02 +09:00
26 changed files with 745 additions and 10419 deletions

View File

@ -1,37 +0,0 @@
// Import the functions you need from the SDKs you need
import { initializeApp } from './firebase-app.js';
import { getAnalytics, logEvent } from './firebase-analytics.js';
// TODO: Add SDKs for Firebase products that you want to use
// https://firebase.google.com/docs/web/setup#available-libraries
// Your web app's Firebase configuration
// For Firebase JS SDK v7.20.0 and later, measurementId is optional
const firebaseConfig = {
apiKey: "{{.FBA_apiKey}}",
authDomain: "{{.FBA_authDomain}}",
databaseURL: "{{.FBA_databaseURL}}",
projectId: "{{.FBA_projectId}}",
storageBucket: "{{.FBA_storageBucket}}",
messagingSenderId: "{{.FBA_messagingSenderId}}",
appId: "{{.FBA_appId}}",
measurementId: "{{.FBA_measurementId}}"
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
const analytics = getAnalytics(app);
// LogEvent('DESKTOP_TEST8');
export function LogEvent(args){
if ( arguments.length == 1) {
logEvent(analytics, arguments[0]);
} else {
logEvent(analytics, arguments[0], arguments[1]);
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

30
config.prod.json Normal file
View File

@ -0,0 +1,30 @@
{
"maingate_mongodb_url": "mongodb://kingdom:Nf9D4XP#TV9L@guudt.vpc.mg.naverncp.com:17017,guue2.vpc.mg.naverncp.com:17017,guue6.vpc.mg.naverncp.com:17017/admin?replicaSet=kd-mongod001",
"autologin_ttl": 604800,
"redirect_base_url": "https://kdmg.action2quare.com",
"google_client_id" : "46698421246-fv2k7chr1j95ju1vm10ogq8prkjt8272.apps.googleusercontent.com",
"google_client_secret" : "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",
"twitter_oauth_key": "1671386871409287169-AIHq3tkoRHK6rPxsWVvvvfXBThqcbn",
"twitter_oauth_secret": "dU3GcLUzRAMOTsXTy8hSSkLI2o2pFJM0kdQi1Qc62pPFn",
"twitter_customer_key": "eROUWahi2yi3f0pLAIMzmtlUB",
"twitter_customer_secret": "zelgFPWgx8o9vqUrBHgTPmuUGDCLjXah33E3pk50u0kxZ9LjIl",
"apple_client_id": "auth.service.action2quare.com",
"apple_privatekey": "-----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgi3HkbNY93XdcNJVa\nAzR895cHxPXYeT0HnAOCzW5IOlOgCgYIKoZIzj0DAQehRANCAAS81nJzJcsZWtdr\n7sAeyqyHFoyCBdmsqI3fvLWYj/5M3MqgMI7pYyVbSmtXT9El/67Y4vz2e/9gllLy\ns0S/XoFo\n-----END PRIVATE KEY-----",
"apple_service_id": "auth.service.action2quare.com",
"apple_team_id": "YC94S4Z6CS",
"apple_key_id": "47UBTLARC8",
"microsoft_client_id": "ebc03204-a5b4-41bf-ac2b-5051615ccf33",
"microsoft_client_secret" : "fa78Q~9C4zEadeOf5ACSFsenP35jHVLKdW.jvcNr",
"gamepot_project_id": "dbfe1334-6dde-43e0-b8a9-cc0733d4c60e",
"gamepot_logincheckapi_url": "https://gamepot.apigw.ntruss.com/gpapps/v1/loginauth",
"firebase_admin_sdk_credentialfile": "kingdom-2b812-firebase-adminsdk-a6j68-d42ae01182.json",
"maingate_global_admins" : [
"mountain@action2quare.com"
]
}

View File

@ -1,8 +1,6 @@
{
"maingate_mongodb_url": "mongodb://...",
"autologin_ttl": 604800,
"acc_del_ttl": 7776000,
"maximum_num_link_account": 10,
"redirect_base_url": "",
"google_client_id" : "",
"google_client_secret" : "",
@ -26,15 +24,6 @@
"firebase_admin_sdk_credentialfile": "",
"firebase_google_analytics_jssdk_apikey": "",
"firebase_google_analytics_jssdk_authdomain": "",
"firebase_google_analytics_jssdk_databaseurl": "",
"firebase_google_analytics_jssdk_projectid": "",
"firebase_google_analytics_jssdk_storagebucket": "",
"firebase_google_analytics_jssdk_messagingsenderid": "",
"firebase_google_analytics_jssdk_apiid": "",
"firebase_google_analytics_jssdk_measurementid": "",
"maingate_global_admins" : [
"mountain@action2quare.com"
]

View File

@ -2,7 +2,9 @@ package core
import (
"bytes"
"crypto/md5"
"encoding/binary"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
@ -16,7 +18,7 @@ import (
"time"
"unsafe"
"repositories.action2quare.com/ayo/gocommon"
common "repositories.action2quare.com/ayo/gocommon"
"repositories.action2quare.com/ayo/gocommon/logger"
"go.mongodb.org/mongo-driver/bson"
@ -24,7 +26,8 @@ import (
"go.mongodb.org/mongo-driver/mongo/options"
)
type FileDocumentDesc struct {
type fileDocumentDesc struct {
Service string `bson:"service" json:"service"`
Key string `bson:"key" json:"key"`
Src string `bson:"src" json:"src"`
Link string `bson:"link" json:"link"`
@ -34,7 +37,7 @@ type FileDocumentDesc struct {
Contents []byte `bson:"contents,omitempty" json:"contents,omitempty"`
}
func (fd *FileDocumentDesc) Save() error {
func (fd *fileDocumentDesc) save() error {
// 새 파일 올라옴
if len(fd.Contents) == 0 {
return nil
@ -63,16 +66,48 @@ func (fd *FileDocumentDesc) Save() error {
if fd.Extract {
switch path.Ext(destFile) {
case ".zip":
err = gocommon.Unzip(destFile)
err = common.Unzip(destFile)
case ".tar":
err = gocommon.Untar(destFile)
err = common.Untar(destFile)
}
}
return err
}
func (caller apiCaller) isAdmin() bool {
if *noauth {
return true
}
v, ok := caller.userinfo["email"]
if !ok {
logger.Println("isVaidUser failed. email is missing :", caller.userinfo)
return false
}
email := v.(string)
if _, ok := caller.globalAdmins[email]; ok {
return true
}
return caller.mg.service().isAdmin(email)
}
func (caller apiCaller) isAdminOrValidToken() bool {
if caller.isAdmin() {
return true
}
return caller.mg.service().isValidToken(caller.apiToken)
}
func (caller apiCaller) filesAPI(w http.ResponseWriter, r *http.Request) error {
if r.Method == "GET" {
// if !caller.isAdminOrValidToken() {
// w.WriteHeader(http.StatusUnauthorized)
// return nil
// }
allfiles, err := caller.mg.mongoClient.All(CollectionFile, options.Find().SetProjection(bson.M{
"contents": 0,
}).SetReturnKey(false))
@ -91,6 +126,11 @@ func (caller apiCaller) filesAPI(w http.ResponseWriter, r *http.Request) error {
return nil
}
// if !caller.isAdminOrValidToken() {
// w.WriteHeader(http.StatusUnauthorized)
// return nil
// }
_, err := caller.mg.mongoClient.Delete(CollectionFile, bson.M{
"key": key,
})
@ -107,6 +147,11 @@ var seq = uint32(0)
func (caller apiCaller) uploadAPI(w http.ResponseWriter, r *http.Request) error {
if r.Method == "PUT" {
servicename := r.FormValue("service")
hasher := md5.New()
hasher.Write([]byte(servicename))
subfolder := hex.EncodeToString(hasher.Sum(nil))[:8]
infile, header, err := r.FormFile("file")
if err != nil {
w.WriteHeader(http.StatusBadRequest)
@ -122,19 +167,20 @@ func (caller apiCaller) uploadAPI(w http.ResponseWriter, r *http.Request) error
var b [5]byte
binary.BigEndian.PutUint32(b[0:4], uint32(time.Now().Unix()))
b[4] = byte(atomic.AddUint32(&seq, 1) % 255)
rf := hex.EncodeToString(b[1:])
newidstr := subfolder + rf
newidbt, _ := hex.DecodeString(newidstr)
newidobj := primitive.NewObjectID()
copy(newidobj[:], b[1:])
copy(newidobj[:], newidbt[:8])
rf := newidobj.Hex()
var link string
if extract {
link = path.Join("static", rf)
link = path.Join("static", subfolder, rf)
} else {
link = path.Join("static", rf, header.Filename)
link = path.Join("static", subfolder, rf, header.Filename)
}
newdoc := FileDocumentDesc{
newdoc := fileDocumentDesc{
Contents: contents,
Src: header.Filename,
Timestamp: time.Now().UTC().Unix(),
@ -142,10 +188,12 @@ func (caller apiCaller) uploadAPI(w http.ResponseWriter, r *http.Request) error
Link: link,
Desc: desc,
Key: rf,
Service: servicename,
}
_, _, err = caller.mg.mongoClient.UpsertOne(CollectionFile, bson.M{
"_id": newidobj,
"key": rf,
"_id": newidobj,
"service": servicename,
"key": rf,
}, newdoc)
if err == nil {
@ -158,81 +206,46 @@ func (caller apiCaller) uploadAPI(w http.ResponseWriter, r *http.Request) error
return nil
}
func (caller apiCaller) blockAPI(w http.ResponseWriter, r *http.Request) error {
mg := caller.mg
if r.Method == "GET" {
json.NewEncoder(w).Encode(mg.bl.all())
} else if r.Method == "PUT" {
body, _ := io.ReadAll(r.Body)
var bipl blockinfoWithStringId
if err := json.Unmarshal(body, &bipl); err != nil {
return err
}
accid, err := primitive.ObjectIDFromHex(bipl.StrId)
if err != nil {
return err
}
bi := blockinfo{
Start: primitive.NewDateTimeFromTime(time.Unix(bipl.StartUnix, 0)),
End: primitive.NewDateTimeFromTime(time.Unix(bipl.EndUnix, 0)),
Reason: bipl.Reason,
}
logger.Println("bi :", accid, bi)
_, _, err = mg.mongoClient.Update(CollectionBlock, bson.M{
"_id": accid,
}, bson.M{
"$set": &bi,
}, options.Update().SetUpsert(true))
if err != nil {
return err
}
} else if r.Method == "DELETE" {
id := r.URL.Query().Get("id")
if len(id) == 0 {
return errors.New("id param is missing")
}
idobj, err := primitive.ObjectIDFromHex(id)
if err != nil {
return err
}
_, _, err = mg.mongoClient.Update(CollectionBlock, bson.M{
"_id": idobj,
}, bson.M{
"$currentDate": bson.M{
"_ts": bson.M{"$type": "date"},
},
}, options.Update().SetUpsert(false))
if err != nil {
return err
}
mg.mongoClient.Delete(CollectionAuth, bson.M{"_id": idobj})
}
return nil
}
func (caller apiCaller) whitelistAPI(w http.ResponseWriter, r *http.Request) error {
mg := caller.mg
queryvals := r.URL.Query()
if r.Method == "GET" {
enc := json.NewEncoder(w)
enc.Encode(mg.wl.all())
// if !caller.isAdminOrValidToken() {
// logger.Println("whitelistAPI failed. not vaild user :", r.Method, caller.userinfo)
// w.WriteHeader(http.StatusUnauthorized)
// return nil
// }
all, err := mg.mongoClient.All(CollectionWhitelist)
if err != nil {
return err
}
if len(all) > 0 {
var notexp []primitive.M
for _, v := range all {
if _, exp := v["_ts"]; !exp {
notexp = append(notexp, v)
}
}
allraw, _ := json.Marshal(notexp)
w.Write(allraw)
}
} else if r.Method == "PUT" {
body, _ := io.ReadAll(r.Body)
var member whitelistmember
if err := json.Unmarshal(body, &member); err != nil {
return err
}
member.ExpiredAt = 0
member.Id = primitive.NilObjectID
// if !caller.isAdminOrValidToken() {
// logger.Println("whitelistAPI failed. not vaild user :", r.Method, caller.userinfo)
// w.WriteHeader(http.StatusUnauthorized)
// return nil
// }
member.Expired = 0
_, _, err := mg.mongoClient.Update(CollectionWhitelist, bson.M{
"_id": primitive.NewObjectID(),
}, bson.M{
@ -243,8 +256,7 @@ func (caller apiCaller) whitelistAPI(w http.ResponseWriter, r *http.Request) err
return err
}
} else if r.Method == "DELETE" {
id := r.URL.Query().Get("id")
id := queryvals.Get("id")
if len(id) == 0 {
return errors.New("id param is missing")
}
@ -270,22 +282,20 @@ func (caller apiCaller) whitelistAPI(w http.ResponseWriter, r *http.Request) err
func (caller apiCaller) serviceAPI(w http.ResponseWriter, r *http.Request) error {
mg := caller.mg
if r.Method == "GET" {
logger.Println("serviceAPI :", r.URL.Path)
if mg.service().Id.IsZero() {
logger.Println(" id is zero")
newService := serviceDescription{
ServiceDescriptionSummary: ServiceDescriptionSummary{
Id: primitive.NewObjectID(),
},
}
if err := newService.prepare(caller.mg); err != nil {
logger.Println(" prepare failed :", err)
return err
}
atomic.StorePointer(&mg.serviceptr, unsafe.Pointer(&newService))
}
w.Write(mg.service().serviceSerialized)
serptr := atomic.LoadPointer(&mg.service().serviceSerialized)
w.Write(*(*[]byte)(serptr))
} else if r.Method == "POST" {
body, _ := io.ReadAll(r.Body)
var service serviceDescription
@ -320,7 +330,8 @@ func (caller apiCaller) serviceAPI(w http.ResponseWriter, r *http.Request) error
func (caller apiCaller) maintenanceAPI(w http.ResponseWriter, r *http.Request) error {
mg := caller.mg
if r.Method == "GET" {
w.Write(mg.service().divisionsSerialized)
serptr := atomic.LoadPointer(&mg.service().divisionsSerialized)
w.Write(*(*[]byte)(serptr))
} else if r.Method == "POST" {
var divs map[string]*Division
dec := json.NewDecoder(r.Body)
@ -344,94 +355,20 @@ func (caller apiCaller) maintenanceAPI(w http.ResponseWriter, r *http.Request) e
return nil
}
func (caller apiCaller) couponAPI(w http.ResponseWriter, r *http.Request) error {
switch r.Method {
case "PUT":
// 쿠폰 생성
logger.Println("begin generateCoupons")
generateCoupons(caller.mg.mongoClient, w, r)
case "POST":
// TODO : 쿠폰 사용
// 쿠폰 사용 표시 해주고 내용을 응답
logger.Println("begin useCoupon")
useCoupon(caller.mg.mongoClient, w, r)
case "GET":
// 쿠폰 조회
if r.Form.Has("code") {
// 쿠폰 코드 조회
logger.Println("begin queryCoupon")
queryCoupon(caller.mg.mongoClient, w, r)
} else if r.Form.Has("name") {
// 쿠폰 코드 다운
logger.Println("begin downloadCoupons")
downloadCoupons(caller.mg.mongoClient, w, r)
} else {
// 쿠폰 이름 목록
logger.Println("begin listAllCouponNames")
listAllCouponNames(caller.mg.mongoClient, w, r)
}
case "DELETE":
// 쿠폰 삭제
logger.Println("begin deleteCoupon")
deleteCoupon(caller.mg.mongoClient, w, r)
}
return nil
}
var errApiTokenMissing = errors.New("mg-x-api-token is missing")
func (caller apiCaller) configAPI(w http.ResponseWriter, r *http.Request) error {
mg := caller.mg
if !*devflag {
apitoken := r.Header.Get("MG-X-API-TOKEN")
if len(apitoken) == 0 {
return errApiTokenMissing
}
apitokenObj, _ := primitive.ObjectIDFromHex(apitoken)
if !mg.service().isValidToken(apitokenObj) {
return fmt.Errorf("mg-x-api-token is not valid : %s", apitoken)
}
apitoken := r.Header.Get("MG-X-API-TOKEN")
if len(apitoken) == 0 {
return errApiTokenMissing
}
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
apitokenObj, _ := primitive.ObjectIDFromHex(apitoken)
if !mg.service().isValidToken(apitokenObj) {
return fmt.Errorf("mg-x-api-token is not valid : %s", apitoken)
}
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
}
@ -455,71 +392,63 @@ func (mg *Maingate) api(w http.ResponseWriter, r *http.Request) {
r.Body.Close()
}()
r.ParseMultipartForm(32 << 20)
var userinfo map[string]any
var apiTokenObj primitive.ObjectID
if !*devflag {
apiToken := r.Header.Get("MG-X-API-TOKEN")
if len(apiToken) > 0 {
if apiToken != mg.maingateConfig.ApiToken {
w.WriteHeader(http.StatusUnauthorized)
return
}
if !*noauth {
authheader := r.Header.Get("Authorization")
if len(authheader) == 0 {
logger.Println("Authorization header is not valid :", authheader)
w.WriteHeader(http.StatusBadRequest)
return
}
obj, err := primitive.ObjectIDFromHex(apiToken)
if err != nil {
logger.Error(err)
w.WriteHeader(http.StatusBadRequest)
return
}
req, _ := http.NewRequest("GET", "https://graph.microsoft.com/oidc/userinfo", nil)
req.Header.Add("Authorization", authheader)
client := &http.Client{}
apiTokenObj = obj
} else {
authheader := r.Header.Get("Authorization")
if len(authheader) == 0 {
logger.Println("Authorization header is not valid :", authheader)
w.WriteHeader(http.StatusUnauthorized)
return
}
resp, err := client.Do(req)
if err != nil {
logger.Println("graph microsoft api call failed :", err)
w.WriteHeader(http.StatusBadRequest)
return
}
defer resp.Body.Close()
req, _ := http.NewRequest("GET", "https://graph.microsoft.com/oidc/userinfo", nil)
req.Header.Add("Authorization", authheader)
client := &http.Client{}
raw, _ := io.ReadAll(resp.Body)
if err = json.Unmarshal(raw, &userinfo); err != nil {
return
}
resp, err := client.Do(req)
if err != nil {
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
}
if _, expired := userinfo["error"]; expired {
w.WriteHeader(http.StatusUnauthorized)
return
}
}
ptr := atomic.LoadPointer(&mg.admins)
adminsptr := (*globalAdmins)(ptr)
if adminsptr.modtime != gocommon.ConfigModTime() {
if adminsptr.modtime != common.ConfigModTime() {
var config globalAdmins
if err := gocommon.LoadConfig(&config); err == nil {
if err := common.LoadConfig(&config); err == nil {
config.parse()
adminsptr = &config
atomic.StorePointer(&mg.admins, unsafe.Pointer(adminsptr))
}
}
apiToken := r.Header.Get("MG-X-API-TOKEN")
var apiTokenObj primitive.ObjectID
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)
caller := apiCaller{
userinfo: userinfo,
@ -541,12 +470,6 @@ func (mg *Maingate) api(w http.ResponseWriter, r *http.Request) {
err = caller.maintenanceAPI(w, r)
} else if strings.HasSuffix(r.URL.Path, "/files") {
err = caller.filesAPI(w, r)
} else if strings.HasSuffix(r.URL.Path, "/block") {
err = caller.blockAPI(w, r)
} else if strings.HasSuffix(r.URL.Path, "/coupon") {
err = caller.couponAPI(w, r)
} else if strings.HasSuffix(r.URL.Path, "/lockcreatechar") {
err = caller.lockcreatecharAPI(w, r)
}
if err != nil {

View File

@ -1,407 +0,0 @@
package core
import (
"encoding/binary"
"encoding/hex"
"encoding/json"
"fmt"
"math/rand"
"net/http"
"strings"
"time"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo/options"
"repositories.action2quare.com/ayo/gocommon"
coupon "repositories.action2quare.com/ayo/gocommon/coupon"
"repositories.action2quare.com/ayo/gocommon/logger"
)
const (
CollectionCoupon = gocommon.CollectionName("coupon")
CollectionCouponUse = gocommon.CollectionName("coupon_use")
)
type couponDoc struct {
Name string `json:"name" bson:"name"`
Effect string `json:"effect" bson:"effect"`
Desc string `json:"desc" bson:"desc"`
Total int64 `json:"total" bson:"total"`
Remains []string `json:"remains,omitempty" bson:"remains,omitempty"`
Used []string `json:"used,omitempty" bson:"used,omitempty"`
Expire int64 `json:"expire" bson:"expire"`
}
func makeCouponKey(roundnum uint32, uid []byte) string {
left := binary.BigEndian.Uint16(uid[0:2])
right := binary.BigEndian.Uint16(uid[2:4])
multi := uint32(left) * uint32(right)
xor := roundnum ^ multi
final := make([]byte, 8)
binary.LittleEndian.PutUint32(final, xor)
copy(final[4:], uid)
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]))
}
func makeCouponCodes(name string, count int) (string, map[string]string) {
checkunique := make(map[string]bool)
keys := make(map[string]string)
uid := make([]byte, 4)
roundHash, roundnum := coupon.MakeCouponRoundHash(name)
seed := time.Now().UnixNano()
for len(keys) < count {
rand.Seed(seed)
rand.Read(uid)
code := makeCouponKey(roundnum, uid)
if _, ok := checkunique[code]; !ok {
checkunique[code] = true
keys[hex.EncodeToString(uid)] = code
}
seed = int64(binary.BigEndian.Uint32(uid))
}
return roundHash, keys
}
func generateCoupons(mongoClient gocommon.MongoClient, w http.ResponseWriter, r *http.Request) {
name, _ := gocommon.ReadStringFormValue(r.Form, "name")
effect, _ := gocommon.ReadStringFormValue(r.Form, "effect")
count, _ := gocommon.ReadIntegerFormValue(r.Form, "count")
desc, _ := gocommon.ReadStringFormValue(r.Form, "desc")
expire, _ := gocommon.ReadIntegerFormValue(r.Form, "expire")
if count == 0 {
logger.Println("[generateCoupons] count == 0")
w.WriteHeader(http.StatusBadRequest)
return
}
roundHash, _ := coupon.MakeCouponRoundHash(name)
roundObj, _ := primitive.ObjectIDFromHex(roundHash + roundHash + roundHash)
if count < 0 {
// 무한 쿠폰이므로 그냥 문서 생성해 주고 끝
if _, _, err := mongoClient.Update(CollectionCoupon, bson.M{
"_id": roundObj,
}, bson.M{
"$set": &couponDoc{
Name: name,
Effect: effect,
Desc: desc,
Total: -1,
Expire: expire,
},
}, options.Update().SetUpsert(true)); err != nil {
logger.Println("[generateCoupons] Update failed :", err)
w.WriteHeader(http.StatusInternalServerError)
}
return
}
// effect가 비어있으면 기존의 roundName에 갯수를 추가해 준다
// effect가 비어있지 않으면 roundName이 겹쳐서는 안된다.
coupondoc, err := mongoClient.FindOne(CollectionCoupon, bson.M{"_id": roundObj})
if err != nil {
logger.Println("[generateCoupons] FindOne failed :", err)
w.WriteHeader(http.StatusInternalServerError)
return
}
lastKeys := make(map[string]bool)
if coupondoc != nil {
if r, ok := coupondoc["remains"]; ok {
remains := r.(primitive.A)
for _, uid := range remains {
lastKeys[uid.(string)] = true
}
}
}
issuedKeys := make(map[string]string)
for len(issuedKeys) < int(count) {
_, vs := makeCouponCodes(name, int(count)-len(issuedKeys))
for k, v := range vs {
if _, ok := lastKeys[k]; !ok {
// 기존 키와 중복되지 않는 것만
issuedKeys[k] = v
}
}
}
var coupons []string
var uids []string
for uid, code := range issuedKeys {
uids = append(uids, uid)
coupons = append(coupons, code)
}
if coupondoc != nil {
_, _, err = mongoClient.Update(CollectionCoupon, bson.M{
"_id": roundObj,
}, bson.M{
"$push": bson.M{"remains": bson.M{"$each": uids}},
"$inc": bson.M{"total": count},
}, options.Update().SetUpsert(true))
} else {
_, _, err = mongoClient.Update(CollectionCoupon, bson.M{
"_id": roundObj,
}, bson.M{
"$push": bson.M{"remains": bson.M{"$each": uids}},
"$set": couponDoc{
Name: name,
Effect: effect,
Desc: desc,
Total: count,
Expire: expire,
},
}, options.Update().SetUpsert(true))
}
if err != nil {
logger.Println("[generateCoupons] Update failed :", err)
w.WriteHeader(http.StatusInternalServerError)
return
}
enc := json.NewEncoder(w)
enc.Encode(coupons)
}
func downloadCoupons(mongoClient gocommon.MongoClient, w http.ResponseWriter, r *http.Request) {
name, _ := gocommon.ReadStringFormValue(r.Form, "name")
if len(name) == 0 {
logger.Println("[downloadCoupons] name is empty")
w.WriteHeader(http.StatusBadRequest)
return
}
round, _ := coupon.MakeCouponRoundHash(name)
roundObj, err := primitive.ObjectIDFromHex(round + round + round)
if err != nil {
// 유효하지 않은 형식의 code
logger.Println("[downloadCoupons] ObjectIDFromHex failed :", err)
w.WriteHeader(http.StatusBadRequest)
return
}
var coupon couponDoc
if err := mongoClient.FindOneAs(CollectionCoupon, bson.M{
"_id": roundObj,
}, &coupon, options.FindOne().SetProjection(bson.M{"_id": 0, "remains": 1})); err != nil {
logger.Println("[downloadCoupons] FindOne failed :", err)
w.WriteHeader(http.StatusInternalServerError)
return
}
roundnum := binary.BigEndian.Uint32(roundObj[:])
var coupons []string
for _, uid := range coupon.Remains {
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.Encode(coupons)
}
func queryCoupon(mongoClient gocommon.MongoClient, w http.ResponseWriter, r *http.Request) {
code, _ := gocommon.ReadStringFormValue(r.Form, "code")
if len(code) == 0 {
logger.Println("[queryCoupon] code is empty")
w.WriteHeader(http.StatusBadRequest)
return
}
round, _ := coupon.DisolveCouponCode(code)
if len(round) == 0 {
// 유효하지 않은 형식의 code
// 쿠폰 이름일 수 있으므로 round hash를 계산한다.
round, _ = coupon.MakeCouponRoundHash(code)
}
roundObj, err := primitive.ObjectIDFromHex(round + round + round)
if err != nil {
// 유효하지 않은 형식의 code
logger.Println("[queryCoupon] ObjectIDFromHex failed :", err)
w.WriteHeader(http.StatusBadRequest)
return
}
var coupon couponDoc
if err := mongoClient.FindOneAs(CollectionCoupon, bson.M{
"_id": roundObj,
}, &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)
w.WriteHeader(http.StatusInternalServerError)
return
}
enc := json.NewEncoder(w)
enc.Encode(coupon)
}
func listAllCouponNames(mongoClient gocommon.MongoClient, w http.ResponseWriter, r *http.Request) {
all, err := mongoClient.FindAll(CollectionCoupon, bson.M{}, options.Find().SetProjection(bson.M{"name": 1}))
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
var names []string
for _, doc := range all {
names = append(names, doc["name"].(string))
}
enc := json.NewEncoder(w)
enc.Encode(names)
}
func useCoupon(mongoClient gocommon.MongoClient, w http.ResponseWriter, r *http.Request) {
acc, ok := gocommon.ReadObjectIDFormValue(r.Form, "accid")
if !ok || acc.IsZero() {
w.WriteHeader(http.StatusBadRequest)
return
}
code, _ := gocommon.ReadStringFormValue(r.Form, "code")
code = strings.TrimSpace(code)
if len(code) == 0 {
w.WriteHeader(http.StatusBadRequest)
return
}
round, key := coupon.DisolveCouponCode(code)
if len(round) == 0 {
// couponId가 쿠폰 이름일 수도 있다. 무한 쿠폰
round, _ = coupon.MakeCouponRoundHash(code)
}
// 쿠폰 사용 유무 검사
alreadyused, err := mongoClient.Exists(CollectionCouponUse, bson.M{
"_id": acc,
"rounds": round,
})
if err != nil {
logger.Println(err)
w.WriteHeader(http.StatusInternalServerError)
return
}
if alreadyused {
// 이미 이 라운드의 쿠폰을 사용한 적이 있다.
w.WriteHeader(http.StatusConflict)
return
}
var coupon couponDoc
roundObj, _ := primitive.ObjectIDFromHex(round + round + round)
if len(key) == 0 {
// 무한 쿠폰일 수 있으므로 존재하는지 확인
if err := mongoClient.FindOneAs(CollectionCoupon, bson.M{
"_id": roundObj,
}, &coupon, options.FindOne().SetProjection(bson.M{"_id": 0, "effect": 1, "name": 1, "total": 1, "expire": 1})); err != nil {
logger.Println(err)
w.WriteHeader(http.StatusInternalServerError)
return
}
if coupon.Total > 0 {
// 무한 쿠폰 아니네?
w.WriteHeader(http.StatusBadRequest)
return
}
} else {
// 쿠폰을 하나 꺼냄
matched, _, err := mongoClient.Update(CollectionCoupon, bson.M{
"_id": roundObj,
"remains": key,
}, bson.M{
"$pull": bson.M{"remains": key},
})
if err != nil {
logger.Println(err)
w.WriteHeader(http.StatusInternalServerError)
return
}
if !matched {
// 쿠폰이 없다.
w.WriteHeader(http.StatusBadRequest)
return
}
// round의 효과 읽기
if err := mongoClient.FindOneAndUpdateAs(CollectionCoupon, bson.M{
"_id": roundObj,
}, bson.M{
"$push": bson.M{"used": key},
}, &coupon, options.FindOneAndUpdate().SetProjection(bson.M{"effect": 1, "expire": 1})); err != nil {
logger.Println(err)
w.WriteHeader(http.StatusInternalServerError)
return
}
}
if coupon.Expire < time.Now().Unix() {
// 쿠폰 만료시간 경과
w.WriteHeader(http.StatusInternalServerError)
return
}
if len(coupon.Effect) == 0 {
// 쿠폰이 없네?
w.WriteHeader(http.StatusBadRequest)
return
}
// 4. 쿠폰은 사용한 것으로 표시
// 이제 이 아래에서 실패하면 이 쿠폰은 못쓴다.
updated, _, err := mongoClient.Update(CollectionCouponUse, bson.M{
"_id": acc,
}, bson.M{
"$push": bson.M{"rounds": round},
"$set": bson.M{round + ".id": code},
"$currentDate": bson.M{round + ".ts": true},
}, options.Update().SetUpsert(true))
if err != nil {
logger.Println(err)
w.WriteHeader(http.StatusInternalServerError)
return
}
if !updated {
logger.Println(err)
w.WriteHeader(http.StatusInternalServerError)
return
}
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

@ -1,39 +0,0 @@
package core
import (
"context"
"fmt"
"testing"
"time"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo/options"
"repositories.action2quare.com/ayo/gocommon"
)
func TestMakeLocalUniqueId(t *testing.T) {
ts := int64(1690815600)
start := primitive.NewDateTimeFromTime(time.Unix(ts, 0))
ts = int64(1693493999)
end := primitive.NewDateTimeFromTime(time.Unix(ts, 0))
fmt.Println(start.Time().Format(time.RFC3339))
fmt.Println(end.Time().Format(time.RFC3339))
mongoClient, err := gocommon.NewMongoClient(context.Background(), "mongodb://121.134.91.160:27018/mountain-maingate?replicaSet=rs0&retrywrites=true", "maingate")
if err != nil {
t.Error(err)
}
bi := blockinfo{
Start: start,
End: end,
Reason: "test",
}
mongoClient.Update(CollectionBlock, bson.M{
"_id": primitive.NewObjectID(),
}, bson.M{
"$set": &bi,
}, options.Update().SetUpsert(true))
}

View File

@ -10,17 +10,14 @@ import (
"io"
"math/big"
"math/rand"
"net"
"net/http"
"os"
"runtime/debug"
"strings"
"sync/atomic"
"text/template"
"time"
"unsafe"
"repositories.action2quare.com/ayo/gocommon"
common "repositories.action2quare.com/ayo/gocommon"
"repositories.action2quare.com/ayo/gocommon/flagx"
"repositories.action2quare.com/ayo/gocommon/logger"
@ -39,21 +36,20 @@ var devflag = flagx.Bool("dev", false, "")
var noauth = flagx.Bool("noauth", false, "")
var (
CollectionLink = gocommon.CollectionName("link")
CollectionAuth = gocommon.CollectionName("auth")
CollectionWhitelist = gocommon.CollectionName("whitelist")
CollectionService = gocommon.CollectionName("service")
CollectionAccount = gocommon.CollectionName("account")
CollectionFile = gocommon.CollectionName("file")
CollectionBlock = gocommon.CollectionName("block")
CollectionPlatformLoginToken = gocommon.CollectionName("platform_login_token") //-- 각 플랫폼에 로그인 및 권한 받아오는 과정에 사용하는 Key
CollectionUserToken = gocommon.CollectionName("usertoken")
CollectionGamepotUserInfo = gocommon.CollectionName("gamepot_userinfo") //-- 클라로부터 수집된 gamepot 정보 - server to server로 유효성이 검증되진 않았지만 수집은 한다.
CollectionFirebaseUserInfo = gocommon.CollectionName("firebase_userinfo") //-- Firebase UserInfo
CollectionLink = common.CollectionName("link")
CollectionAuth = common.CollectionName("auth")
CollectionWhitelist = common.CollectionName("whitelist")
CollectionService = common.CollectionName("service")
CollectionAccount = common.CollectionName("account")
CollectionFile = common.CollectionName("file")
CollectionBlock = common.CollectionName("block")
CollectionPlatformLoginToken = common.CollectionName("platform_login_token") //-- 각 플랫폼에 로그인 및 권한 받아오는 과정에 사용하는 Key
CollectionUserToken = common.CollectionName("usertoken")
CollectionGamepotUserInfo = common.CollectionName("gamepot_userinfo") //-- 클라로부터 수집된 gamepot 정보 - server to server로 유효성이 검증되진 않았지만 수집은 한다.
CollectionFirebaseUserInfo = common.CollectionName("firebase_userinfo") //-- Firebase UserInfo
)
const (
AuthPlatformSteamSDK = "steam"
AuthPlatformFirebaseAuth = "firebase"
AuthPlatformGoogle = "google"
AuthPlatformMicrosoft = "microsoft"
@ -75,10 +71,10 @@ func SessionTTL() time.Duration {
}
type mongoAuthCell struct {
src *gocommon.Authinfo
src *common.Authinfo
}
func (ac *mongoAuthCell) ToAuthinfo() *gocommon.Authinfo {
func (ac *mongoAuthCell) ToAuthinfo() *common.Authinfo {
if ac.src == nil {
logger.Error("mongoAuthCell ToAuthinfo failed. ac.src is nil")
}
@ -90,15 +86,15 @@ func (ac *mongoAuthCell) ToBytes() []byte {
return bt
}
func makeAuthCollection(mongoClient gocommon.MongoClient, sessionTTL time.Duration) *gocommon.AuthCollection {
authcoll := gocommon.MakeAuthCollection(sessionTTL)
func makeAuthCollection(mongoClient common.MongoClient, sessionTTL time.Duration) *common.AuthCollection {
authcoll := common.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 {
authcoll.QuerySession = func(sk string, token string) common.AuthinfoCell {
skid, _ := primitive.ObjectIDFromHex(sk)
var outcell mongoAuthCell
err := mongoClient.FindOneAs(CollectionAuth, bson.M{
@ -123,10 +119,7 @@ func makeAuthCollection(mongoClient gocommon.MongoClient, sessionTTL time.Durati
type maingateConfig struct {
Mongo string `json:"maingate_mongodb_url"`
SessionTTL int64 `json:"maingate_session_ttl"`
ApiToken string `json:"maingate_api_token"`
Autologin_ttl int64 `json:"autologin_ttl"`
AccDelTTL int64 `json:"acc_del_ttl"`
MaximumNumLinkAccount int64 `json:"maximum_num_link_account"`
RedirectBaseUrl string `json:"redirect_base_url"`
GoogleClientId string `json:"google_client_id"`
GoogleClientSecret string `json:"google_client_secret"`
@ -144,20 +137,6 @@ type maingateConfig struct {
GamepotProjectId string `json:"gamepot_project_id"`
GamepotLoginCheckAPIURL string `json:"gamepot_logincheckapi_url"`
FirebaseAdminSDKCredentialFile string `json:"firebase_admin_sdk_credentialfile"`
SteamAppId string `json:"steam_app_id"`
SteamPublisherAuthKey string `json:"steam_publisher_authkey"`
Firebase_Google_Analytics_JS_SDK_Config
}
type Firebase_Google_Analytics_JS_SDK_Config struct {
FGA_apiKey string `json:"firebase_google_analytics_jssdk_apikey"`
FGA_authDomain string `json:"firebase_google_analytics_jssdk_authdomain"`
FGA_databaseURL string `json:"firebase_google_analytics_jssdk_databaseurl"`
FGA_projectId string `json:"firebase_google_analytics_jssdk_projectid"`
FGA_storageBucket string `json:"firebase_google_analytics_jssdk_storagebucket"`
FGA_messagingSenderId string `json:"firebase_google_analytics_jssdk_messagingsenderid"`
FGA_appId string `json:"firebase_google_analytics_jssdk_apiid"`
FGA_measurementId string `json:"ffirebase_google_analytics_jssdk_measurementid"`
}
type globalAdmins struct {
@ -172,21 +151,20 @@ func (ga *globalAdmins) parse() {
parsed[admin] = true
}
ga.emails = parsed
ga.modtime = gocommon.ConfigModTime()
ga.modtime = common.ConfigModTime()
}
// Maingate :
type Maingate struct {
maingateConfig
mongoClient gocommon.MongoClient
mongoClient common.MongoClient
auths *gocommon.AuthCollection
auths *common.AuthCollection
//services servicelist
serviceptr unsafe.Pointer
admins unsafe.Pointer
wl memberContainerPtr[string, *whitelistmember]
bl memberContainerPtr[primitive.ObjectID, *blockinfo]
wl whitelist
tokenEndpoints map[string]string
authorizationEndpoints map[string]string
@ -196,15 +174,31 @@ type Maingate struct {
firebaseAppContext context.Context
}
var collectionNameMod = int32(0)
// New :
func New(ctx context.Context) (*Maingate, error) {
if *devflag && atomic.AddInt32(&collectionNameMod, 1) == 1 {
hostname, _ := os.Hostname()
CollectionLink = common.CollectionName(fmt.Sprintf("%s-%s", hostname, string(CollectionLink)))
CollectionAuth = common.CollectionName(fmt.Sprintf("%s-%s", hostname, string(CollectionAuth)))
CollectionWhitelist = common.CollectionName(fmt.Sprintf("%s-%s", hostname, string(CollectionWhitelist)))
CollectionService = common.CollectionName(fmt.Sprintf("%s-%s", hostname, string(CollectionService)))
CollectionAccount = common.CollectionName(fmt.Sprintf("%s-%s", hostname, string(CollectionAccount)))
CollectionBlock = common.CollectionName(fmt.Sprintf("%s-%s", hostname, string(CollectionBlock)))
CollectionPlatformLoginToken = common.CollectionName(fmt.Sprintf("%s-%s", hostname, string(CollectionPlatformLoginToken)))
CollectionUserToken = common.CollectionName(fmt.Sprintf("%s-%s", hostname, string(CollectionUserToken)))
CollectionGamepotUserInfo = common.CollectionName(fmt.Sprintf("%s-%s", hostname, string(CollectionGamepotUserInfo)))
CollectionFirebaseUserInfo = common.CollectionName(fmt.Sprintf("%s-%s", hostname, string(CollectionFirebaseUserInfo)))
}
var config maingateConfig
if err := gocommon.LoadConfig(&config); err != nil {
if err := common.LoadConfig(&config); err != nil {
return nil, err
}
var admins globalAdmins
if err := gocommon.LoadConfig(&admins); err == nil {
if err := common.LoadConfig(&admins); err == nil {
admins.parse()
}
@ -223,6 +217,7 @@ func New(ctx context.Context) (*Maingate, error) {
err := mg.prepare(ctx)
if err != nil {
logger.Error("mg.prepare() failed :", err)
return nil, err
}
@ -302,107 +297,100 @@ 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) {
if err := mg.discoverOpenIdConfiguration(AuthPlatformMicrosoft, "https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration"); err != nil {
return makeErrorWithStack(err)
return err
}
if err := mg.discoverOpenIdConfiguration("google", "https://accounts.google.com/.well-known/openid-configuration"); err != nil {
return makeErrorWithStack(err)
return err
}
// redis에서 env를 가져온 후에
mg.mongoClient, err = gocommon.NewMongoClient(context, mg.Mongo, "maingate")
mg.mongoClient, err = common.NewMongoClient(context, mg.Mongo, "maingate")
if err != nil {
return makeErrorWithStack(err)
}
if err = mg.mongoClient.MakeUniqueIndices(CollectionCouponUse, map[string]bson.D{
"idrounds": {{Key: "_id", Value: 1}, {Key: "rounds", Value: 1}},
}); err != nil {
return err
}
if err = mg.mongoClient.MakeUniqueIndices(CollectionAuth, map[string]bson.D{
"skonly": {{Key: "sk", Value: 1}},
}); err != nil {
return makeErrorWithStack(err)
return err
}
if err = mg.mongoClient.MakeUniqueIndices(CollectionLink, map[string]bson.D{
"platformuid": {{Key: "platform", Value: 1}, {Key: "uid", Value: 1}},
}); err != nil {
return makeErrorWithStack(err)
return err
}
if err = mg.mongoClient.MakeUniqueIndices(CollectionLink, map[string]bson.D{
"emailplatform": {{Key: "email", Value: 1}, {Key: "platform", Value: 1}},
}); err != nil {
return makeErrorWithStack(err)
return err
}
if err = mg.mongoClient.MakeIndices(CollectionAccount, map[string]bson.D{
"accid": {{Key: "accid", Value: 1}},
if err = mg.mongoClient.MakeIndices(CollectionWhitelist, map[string]bson.D{
"service": {{Key: "service", Value: 1}},
}); err != nil {
return makeErrorWithStack(err)
return err
}
if err = mg.mongoClient.MakeIndices(CollectionFile, map[string]bson.D{
"service": {{Key: "service", Value: 1}},
}); err != nil {
return err
}
if err = mg.mongoClient.MakeUniqueIndices(CollectionFile, map[string]bson.D{
"keyonly": {{Key: "key", Value: 1}},
"sk": {{Key: "service", Value: 1}, {Key: "key", Value: 1}},
}); err != nil {
return makeErrorWithStack(err)
return 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에 삭제 알려주기 위함
if err = mg.mongoClient.MakeExpireIndex(CollectionWhitelist, 10); err != nil {
return makeErrorWithStack(err)
return err
}
if err = mg.mongoClient.MakeExpireIndex(CollectionAuth, int32(mg.SessionTTL+300)); err != nil {
return makeErrorWithStack(err)
return err
}
if err = mg.mongoClient.MakeUniqueIndices(CollectionBlock, map[string]bson.D{
"codeaccid": {{Key: "code", Value: 1}, {Key: "accid", Value: 1}},
}); err != nil {
return err
}
if err = mg.mongoClient.MakeExpireIndex(CollectionBlock, int32(3)); err != nil {
return makeErrorWithStack(err)
return err
}
if err = mg.mongoClient.MakeUniqueIndices(CollectionPlatformLoginToken, map[string]bson.D{
"platformauthtoken": {{Key: "platform", Value: 1}, {Key: "key", Value: 1}},
}); err != nil {
return makeErrorWithStack(err)
return err
}
if err = mg.mongoClient.MakeExpireIndex(CollectionPlatformLoginToken, int32(mg.SessionTTL+300)); err != nil {
return makeErrorWithStack(err)
return err
}
if err = mg.mongoClient.MakeUniqueIndices(CollectionUserToken, map[string]bson.D{
"platformusertoken": {{Key: "platform", Value: 1}, {Key: "userid", Value: 1}},
}); err != nil {
return makeErrorWithStack(err)
return err
}
if err = mg.mongoClient.MakeUniqueIndices(CollectionGamepotUserInfo, map[string]bson.D{
"gamepotuserid": {{Key: "gamepotuserid", Value: 1}},
}); err != nil {
return makeErrorWithStack(err)
return err
}
if err = mg.mongoClient.MakeUniqueIndices(CollectionFirebaseUserInfo, map[string]bson.D{
"firebaseuserid": {{Key: "firebaseuserid", Value: 1}},
}); err != nil {
return makeErrorWithStack(err)
return err
}
mg.auths = makeAuthCollection(mg.mongoClient, time.Duration(mg.SessionTTL*int64(time.Second)))
@ -414,7 +402,7 @@ func (mg *Maingate) prepare(context context.Context) (err error) {
if err = mg.mongoClient.FindAllAs(CollectionFile, nil, &preall, options.Find().SetProjection(bson.M{
"link": 1,
})); err != nil {
return makeErrorWithStack(err)
return err
}
for _, pre := range preall {
@ -424,41 +412,62 @@ func (mg *Maingate) prepare(context context.Context) (err error) {
}
logger.Println("saving files :", pre.Link)
var fulldoc FileDocumentDesc
var fulldoc fileDocumentDesc
err = mg.mongoClient.FindOneAs(CollectionFile, bson.M{
"_id": pre.Id,
}, &fulldoc)
if err != nil {
return makeErrorWithStack(err)
return err
}
err = fulldoc.Save()
err = fulldoc.save()
if err != nil {
return makeErrorWithStack(err)
return err
}
}
var whites []*whitelistmember
var whites []whitelistmember
if err := mg.mongoClient.AllAs(CollectionWhitelist, &whites, options.Find().SetReturnKey(false)); err != nil {
return makeErrorWithStack(err)
return err
}
mg.wl.init(whites)
var blocks []*blockinfo
if err := mg.mongoClient.AllAs(CollectionBlock, &blocks); err != nil {
return makeErrorWithStack(err)
}
mg.bl.init(blocks)
go watchAuthCollection(context, mg.auths, mg.mongoClient)
go mg.wl.watchCollection(context, CollectionWhitelist, mg.mongoClient)
go mg.bl.watchCollection(context, CollectionBlock, mg.mongoClient)
go mg.watchWhitelistCollection(context)
return nil
}
func whitelistKey(email string) string {
if strings.HasPrefix(email, "*@") {
// 도메인 전체 허용
return email[2:]
}
return email
}
func (mg *Maingate) RegisterHandlers(ctx context.Context, serveMux *http.ServeMux, prefix string) error {
var allServices []*serviceDescription
if err := mg.mongoClient.AllAs(CollectionService, &allServices, options.Find().SetReturnKey(false)); err != nil {
if *noauth {
host, _ := os.Hostname()
empty := serviceDescription{
ServiceDescriptionSummary: ServiceDescriptionSummary{
ServiceCode: "000000000000",
},
Divisions: map[string]*Division{
host: {
DivisionForUser: DivisionForUser{
Priority: 0,
State: DivisionState_FullOpen,
},
Url: fmt.Sprintf("http://%s.actionsquare.corp/warehouse", host),
},
},
}
empty.prepare(mg)
allServices = append(allServices, &empty)
} else if err := mg.mongoClient.AllAs(CollectionService, &allServices, options.Find().SetReturnKey(false)); err != nil {
return err
}
@ -473,54 +482,14 @@ func (mg *Maingate) RegisterHandlers(ctx context.Context, serveMux *http.ServeMu
Id: primitive.NewObjectID(),
},
}
if *devflag {
host, _ := os.Hostname()
addrs, err := net.InterfaceAddrs()
if err != nil {
return err
}
ipaddr := "127.0.0.1"
for _, addr := range addrs {
if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
if ipnet.IP.To4() != nil && ipnet.IP.IsPrivate() {
ipaddr = ipnet.IP.String()
}
}
}
empty.Divisions = map[string]*Division{
host: {
DivisionForUser: DivisionForUser{
Priority: 0,
State: DivisionState_FullOpen,
LockCreateChar: false,
},
Url: fmt.Sprintf("http://%s/warehouse", ipaddr),
},
}
}
empty.prepare(mg)
atomic.StorePointer(&mg.serviceptr, unsafe.Pointer(&empty))
filter := bson.M{"_id": empty.Id}
_, _, err := mg.mongoClient.Update(CollectionService, filter, bson.M{
"$set": &empty,
}, options.Update().SetUpsert(true))
if err != nil {
return err
}
}
logger.Println("Service is registered :", mg.service().ServiceCode)
serveMux.HandleFunc(gocommon.MakeHttpHandlerPattern(prefix, mg.service().ServiceCode, "/"), func(w http.ResponseWriter, r *http.Request) {
mg.service().serveHTTP(w, r)
})
serveMux.HandleFunc(gocommon.MakeHttpHandlerPattern(prefix, "api/"), mg.api)
serveMux.HandleFunc(gocommon.MakeHttpHandlerPattern(prefix, "query/"), mg.query)
serveMux.Handle(common.MakeHttpHandlerPattern(prefix, mg.service().ServiceCode, "/"), mg.service())
serveMux.HandleFunc(common.MakeHttpHandlerPattern(prefix, "api/"), mg.api)
serveMux.HandleFunc(common.MakeHttpHandlerPattern(prefix, "query/"), mg.query)
configraw, _ := json.Marshal(mg.maingateConfig)
var convertedConfig map[string]any
@ -528,7 +497,7 @@ func (mg *Maingate) RegisterHandlers(ctx context.Context, serveMux *http.ServeMu
return err
}
serveMux.HandleFunc(gocommon.MakeHttpHandlerPattern(prefix, "config"), func(w http.ResponseWriter, r *http.Request) {
serveMux.HandleFunc(common.MakeHttpHandlerPattern(prefix, "config"), func(w http.ResponseWriter, r *http.Request) {
defer func() {
s := recover()
if s != nil {
@ -536,22 +505,17 @@ func (mg *Maingate) RegisterHandlers(ctx context.Context, serveMux *http.ServeMu
}
}()
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) {
convertedConfig["divisions"] = mg.service().Divisions
}
} else {
convertedConfig["divisions"] = mg.service().Divisions
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) {
convertedConfig["divisions"] = mg.service().Divisions
}
enc := json.NewEncoder(w)
enc.Encode(convertedConfig)
})
@ -561,44 +525,30 @@ func (mg *Maingate) RegisterHandlers(ctx context.Context, serveMux *http.ServeMu
return err
}
cfsx := http.FileServer(http.Dir("console"))
pattern := gocommon.MakeHttpHandlerPattern(prefix, "console", "/")
serveMux.Handle(pattern, http.StripPrefix(pattern, cfsx))
logger.Println("maingate console registered :", pattern)
fsx := http.FileServer(http.Dir("./console"))
serveMux.Handle(common.MakeHttpHandlerPattern(prefix, "console/"), http.StripPrefix("/console/", fsx))
staticfs := http.FileServer(http.Dir("static"))
pattern = gocommon.MakeHttpHandlerPattern(prefix, "static", "/")
serveMux.Handle(pattern, http.StripPrefix(pattern, staticfs))
logger.Println("maingate static registered :", pattern)
ssx := http.FileServer(http.Dir("./static"))
serveMux.Handle(common.MakeHttpHandlerPattern(prefix, "static/"), http.StripPrefix("/static/", ssx))
fbafs := http.FileServer(http.Dir("fba"))
pattern = gocommon.MakeHttpHandlerPattern(prefix, "fba", "/")
serveMux.Handle(pattern, http.StripPrefix(pattern, fbafs))
logger.Println("google_analytics static registered :", pattern)
serveMux.HandleFunc(common.MakeHttpHandlerPattern(prefix, "request_login_url", AuthPlatformGoogle), mg.platform_google_get_login_url)
serveMux.HandleFunc(common.MakeHttpHandlerPattern(prefix, "authorize", AuthPlatformGoogle), mg.platform_google_authorize)
serveMux.HandleFunc(common.MakeHttpHandlerPattern(prefix, "authorize_result", AuthPlatformGoogle), mg.platform_google_authorize_result)
serveMux.HandleFunc(gocommon.MakeHttpHandlerPattern(prefix, "fba", "fb-ga.min.js"), mg.google_analytics_js)
logger.Println("google_analytics.js static registered :", pattern)
serveMux.HandleFunc(common.MakeHttpHandlerPattern(prefix, "request_login_url", AuthPlatformMicrosoft), mg.platform_microsoft_get_login_url)
serveMux.HandleFunc(common.MakeHttpHandlerPattern(prefix, "authorize", AuthPlatformMicrosoft), mg.platform_microsoft_authorize)
serveMux.HandleFunc(common.MakeHttpHandlerPattern(prefix, "authorize_result", AuthPlatformMicrosoft), mg.platform_microsoft_authorize_result)
serveMux.HandleFunc(gocommon.MakeHttpHandlerPattern(prefix, "request_login_url", AuthPlatformGoogle), mg.platform_google_get_login_url)
serveMux.HandleFunc(gocommon.MakeHttpHandlerPattern(prefix, "authorize", AuthPlatformGoogle), mg.platform_google_authorize)
serveMux.HandleFunc(gocommon.MakeHttpHandlerPattern(prefix, "authorize_result", AuthPlatformGoogle), mg.platform_google_authorize_result)
serveMux.HandleFunc(common.MakeHttpHandlerPattern(prefix, "request_login_url", AuthPlatformTwitter), mg.platform_twitter_get_login_url)
serveMux.HandleFunc(common.MakeHttpHandlerPattern(prefix, "authorize", AuthPlatformTwitter), mg.platform_twitter_authorize)
serveMux.HandleFunc(common.MakeHttpHandlerPattern(prefix, "authorize_result", AuthPlatformTwitter), mg.platform_twitter_authorize_result)
serveMux.HandleFunc(gocommon.MakeHttpHandlerPattern(prefix, "request_login_url", AuthPlatformMicrosoft), mg.platform_microsoft_get_login_url)
serveMux.HandleFunc(gocommon.MakeHttpHandlerPattern(prefix, "authorize", AuthPlatformMicrosoft), mg.platform_microsoft_authorize)
serveMux.HandleFunc(gocommon.MakeHttpHandlerPattern(prefix, "authorize_result", AuthPlatformMicrosoft), mg.platform_microsoft_authorize_result)
serveMux.HandleFunc(common.MakeHttpHandlerPattern(prefix, "request_login_url", AuthPlatformApple), mg.platform_apple_get_login_url)
serveMux.HandleFunc(common.MakeHttpHandlerPattern(prefix, "authorize", AuthPlatformApple), mg.platform_apple_authorize)
serveMux.HandleFunc(common.MakeHttpHandlerPattern(prefix, "authorize_result", AuthPlatformApple), mg.platform_apple_authorize_result)
serveMux.HandleFunc(gocommon.MakeHttpHandlerPattern(prefix, "request_login_url", AuthPlatformTwitter), mg.platform_twitter_get_login_url)
serveMux.HandleFunc(gocommon.MakeHttpHandlerPattern(prefix, "authorize", AuthPlatformTwitter), mg.platform_twitter_authorize)
serveMux.HandleFunc(gocommon.MakeHttpHandlerPattern(prefix, "authorize_result", AuthPlatformTwitter), mg.platform_twitter_authorize_result)
serveMux.HandleFunc(gocommon.MakeHttpHandlerPattern(prefix, "request_login_url", AuthPlatformApple), mg.platform_apple_get_login_url)
serveMux.HandleFunc(gocommon.MakeHttpHandlerPattern(prefix, "authorize", AuthPlatformApple), mg.platform_apple_authorize)
serveMux.HandleFunc(gocommon.MakeHttpHandlerPattern(prefix, "authorize_result", AuthPlatformApple), mg.platform_apple_authorize_result)
serveMux.HandleFunc(gocommon.MakeHttpHandlerPattern(prefix, "request_login_url", AuthPlatformFirebaseAuth), mg.platform_firebaseauth_get_login_url)
serveMux.HandleFunc(gocommon.MakeHttpHandlerPattern(prefix, "authorize_sdk", AuthPlatformFirebaseAuth), mg.platform_firebaseauth_authorize_sdk)
serveMux.HandleFunc(gocommon.MakeHttpHandlerPattern(prefix, "authorize_sdk", AuthPlatformSteamSDK), mg.platform_steamsdk_authorize)
serveMux.HandleFunc(common.MakeHttpHandlerPattern(prefix, "request_login_url", AuthPlatformFirebaseAuth), mg.platform_firebaseauth_get_login_url)
serveMux.HandleFunc(common.MakeHttpHandlerPattern(prefix, "authorize_sdk", AuthPlatformFirebaseAuth), mg.platform_firebaseauth_authorize_sdk)
go mg.watchServiceCollection(ctx, serveMux, prefix)
go mg.watchFileCollection(ctx, serveMux, prefix)
@ -637,7 +587,7 @@ func (mg *Maingate) query(w http.ResponseWriter, r *http.Request) {
return
}
if !*devflag {
if !*noauth {
apitoken := r.Header.Get("MG-X-API-TOKEN")
if len(apitoken) == 0 {
logger.Println("MG-X-API-TOKEN is missing")
@ -769,8 +719,6 @@ func (mg *Maingate) updateUserinfo(info usertokeninfo) (bool, string, string) {
success, userid, email = mg.platform_microsoft_getuserinfo(info)
case AuthPlatformGoogle:
success, userid, email = mg.platform_google_getuserinfo(info)
case AuthPlatformSteamSDK:
success, userid, email = mg.platform_steamsdk_getuserinfo(info)
case AuthPlatformFirebaseAuth:
success, userid, email = mg.platform_firebase_getuserinfo(info)
}
@ -811,18 +759,13 @@ func (mg *Maingate) getProviderInfo(platform string, uid string) (string, string
if 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:
provider = platform
providerid = uid
if provider == "" || providerid == "" {
return "", "", errors.New("getProviderInfo - provider info not found: " + provider + " / " + providerid)
}
}
if provider == "" || providerid == "" {
return "", "", errors.New("getProviderInfo - provider info not found: " + provider + " / " + providerid)
}
return provider, providerid, nil
@ -985,31 +928,3 @@ func JWTparseCode(keyurl string, code string) (string, string, string) {
//--- nonce 체크 필요하다.
return claims["sub"].(string), email, nonce
}
func (mg *Maingate) google_analytics_html(w http.ResponseWriter, r *http.Request) {
parsedTemplate, _ := template.ParseFiles("template/track-event.html")
err := parsedTemplate.Execute(w, nil)
if err != nil {
logger.Error("Error executing template :", err)
return
}
}
func (mg *Maingate) google_analytics_js(w http.ResponseWriter, r *http.Request) {
fgaconfig := Firebase_Google_Analytics_JS_SDK_Config{
FGA_apiKey: mg.FGA_apiKey,
FGA_authDomain: mg.FGA_authDomain,
FGA_databaseURL: mg.FGA_databaseURL,
FGA_projectId: mg.FGA_projectId,
FGA_storageBucket: mg.FGA_storageBucket,
FGA_messagingSenderId: mg.FGA_messagingSenderId,
FGA_appId: mg.FGA_appId,
FGA_measurementId: mg.FGA_measurementId,
}
parsedTemplate, _ := template.ParseFiles("template/fb-ga.min.js")
err := parsedTemplate.Execute(w, fgaconfig)
if err != nil {
logger.Error("Error executing template :", err)
return
}
}

View File

@ -1,177 +0,0 @@
package core
import (
"context"
"sync/atomic"
"time"
"unsafe"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
"repositories.action2quare.com/ayo/gocommon"
"repositories.action2quare.com/ayo/gocommon/logger"
)
type memberContraints[K comparable] interface {
Key() K
Expired() bool
}
type memberContainerPtr[K comparable, T memberContraints[K]] struct {
ptr unsafe.Pointer
}
func (p *memberContainerPtr[K, T]) init(ms []T) {
next := map[K]T{}
for _, m := range ms {
next[m.Key()] = m
}
atomic.StorePointer(&p.ptr, unsafe.Pointer(&next))
}
func (p *memberContainerPtr[K, T]) add(m T) {
ptr := atomic.LoadPointer(&p.ptr)
src := (*map[K]T)(ptr)
next := map[K]T{}
for k, v := range *src {
next[k] = v
}
next[m.Key()] = m
atomic.StorePointer(&p.ptr, unsafe.Pointer(&next))
}
func (p *memberContainerPtr[K, T]) get(key K) (T, bool) {
ptr := atomic.LoadPointer(&p.ptr)
src := (*map[K]T)(ptr)
out, found := (*src)[key]
return out, found
}
func (p *memberContainerPtr[K, T]) remove(key K) {
ptr := atomic.LoadPointer(&p.ptr)
src := (*map[K]T)(ptr)
next := map[K]T{}
for k, v := range *src {
next[k] = v
}
delete(next, key)
atomic.StorePointer(&p.ptr, unsafe.Pointer(&next))
}
type memberPipelineDocument[K comparable, T memberContraints[K]] struct {
OperationType string `bson:"operationType"`
DocumentKey struct {
Id primitive.ObjectID `bson:"_id"`
} `bson:"documentKey"`
Member T `bson:"fullDocument"`
}
func (p *memberContainerPtr[K, T]) all() []T {
ptr := atomic.LoadPointer(&p.ptr)
src := (*map[K]T)(ptr)
out := make([]T, 0, len(*src))
for _, m := range *src {
if m.Expired() {
continue
}
out = append(out, m)
}
return out
}
func (p *memberContainerPtr[K, T]) contains(key K, out *T) bool {
ptr := atomic.LoadPointer(&p.ptr)
src := (*map[K]T)(ptr)
found, exists := (*src)[key]
if exists {
if found.Expired() {
p.remove(key)
return false
}
if out != nil {
*out = found
}
return true
}
return false
}
func (p *memberContainerPtr[K, T]) watchCollection(parentctx context.Context, coll gocommon.CollectionName, mc 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{
"update",
"insert",
}},
}},
},
}}
projectStage := bson.D{
{
Key: "$project", Value: bson.D{
{Key: "documentKey", Value: 1},
{Key: "fullDocument", Value: 1},
},
},
}
var stream *mongo.ChangeStream
var err error
var ctx context.Context
for {
if stream == nil {
stream, err = mc.Watch(coll, mongo.Pipeline{matchStage, projectStage})
if err != nil {
logger.Error("watchCollection watch failed :", err)
time.Sleep(time.Minute)
continue
}
ctx = context.TODO()
}
changed := stream.TryNext(ctx)
if ctx.Err() != nil {
logger.Error("watchCollection stream.TryNext failed. process should be restarted! :", ctx.Err().Error())
break
}
if changed {
var data memberPipelineDocument[K, T]
if err := stream.Decode(&data); err == nil {
p.add(data.Member)
} else {
logger.Error("watchCollection stream.Decode failed :", err)
}
} else if stream.Err() != nil || stream.ID() == 0 {
select {
case <-ctx.Done():
logger.Println("watchCollection is done")
stream.Close(ctx)
return
case <-time.After(time.Second):
logger.Error("watchCollection stream error :", stream.Err())
stream.Close(ctx)
stream = nil
}
} else {
time.Sleep(time.Second)
}
}
}

View File

@ -1,126 +0,0 @@
package core
import (
"encoding/json"
"errors"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
"strings"
"time"
"repositories.action2quare.com/ayo/gocommon/logger"
)
type SteamSDKAuthInfo struct {
UserSteamId string `json:"steamid"`
UserAuthToken string `json:"authtoken"`
}
func (mg *Maingate) platform_steamsdk_authorize(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
brinfo, err := mg.GetUserBrowserInfo(r)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
logger.Error(err)
return
}
var authinfo SteamSDKAuthInfo
err = json.NewDecoder(r.Body).Decode(&authinfo)
if err != nil {
logger.Println("authinfo decoding fail:", err)
w.WriteHeader(http.StatusBadRequest)
return
}
if !*noauth {
err = authenticateSteamUser(mg.SteamPublisherAuthKey, mg.SteamAppId, authinfo.UserSteamId, authinfo.UserAuthToken)
}
if err == nil {
acceestoken_expire_time := time.Date(2999, 1, int(time.January), 0, 0, 0, 0, time.UTC).Unix()
var info usertokeninfo
info.platform = AuthPlatformSteamSDK
info.userid = authinfo.UserSteamId
info.token = authinfo.UserAuthToken
info.brinfo = brinfo
//info.accesstoken = respReferesh.AccessToken
info.accesstoken_expire_time = acceestoken_expire_time
mg.setUserToken(info)
params := url.Values{}
params.Add("id", authinfo.UserSteamId)
params.Add("authtype", AuthPlatformSteamSDK)
w.Write([]byte("?" + params.Encode()))
//http.Redirect(w, r, "actionsquare://login?"+Result, http.StatusSeeOther)
} else {
logger.Println(err)
http.Redirect(w, r, "actionsquare://error", http.StatusSeeOther)
}
}
func authenticateSteamUser(pubkey, appid, playerid, ticket string) error {
// Returns: The user's 64-bit SteamID if the user's ticket is valid
url := fmt.Sprintf("https://partner.steam-api.com/ISteamUserAuth/AuthenticateUserTicket/v1/?key=%s&appid=%s&ticket=%s", pubkey, appid, ticket)
resp, e := http.Get(url)
if e != nil {
return e
}
defer func() {
io.Copy(io.Discard, resp.Body)
resp.Body.Close()
}()
body, e := ioutil.ReadAll(resp.Body)
if e != nil {
return e
}
// fmt.Println(url)
// fmt.Println(string(body))
var doc map[string]interface{}
if err := json.Unmarshal(body, &doc); err != nil {
return err
}
if v, ok := doc["response"]; ok {
response := v.(map[string]interface{})
if v, ok = response["params"]; ok {
paramsnode := v.(map[string]interface{})
if v, ok = paramsnode["result"]; ok {
if v.(string) == "OK" {
if v, ok = paramsnode["steamid"]; ok {
// playerid에는 빌드 구성 suffix가 붙어있는 상태이므로 == 비교가 아니라 HasPrefix로 비교
if strings.HasPrefix(playerid, v.(string)) {
return nil
}
}
} else if v.(string) == "Invalid ticket" {
return errors.New("steam: invalid ticket")
}
}
} else if errdocraw, ok := response["error"]; ok {
errdoc := errdocraw.(map[string]interface{})
desc := errdoc["errordesc"].(string)
return errors.New(desc)
}
}
return errors.New("steam: response is not expected")
}
func (mg *Maingate) platform_steamsdk_getuserinfo(info usertokeninfo) (bool, string, string) {
// Steam은 이메일 정보를 받을수 없기 때문에 dummy임시 주소 할당하여 리턴한다.
dummyEmail := fmt.Sprintf("__dummy_%s@steamtemp__", info.userid)
return true, info.userid, dummyEmail
}

View File

@ -222,13 +222,14 @@ func (mg *Maingate) platform_twitter_authorize_result(w http.ResponseWriter, r *
func (mg *Maingate) platform_twitter_getuserinfo(token, secret string) (bool, string, string) {
result := mg.CallTwitterAPI("https://api.twitter.com/1.1/account/verify_credentials.json?include_email=true", "GET", token, secret, mg.GeneratePlatformLoginNonceKey())
result := mg.CallTwitterAPI("https://api.twitter.com/2/users/me", "GET", token, secret, mg.GeneratePlatformLoginNonceKey())
var TwitterUserInfo struct {
Id string `json:"id_str"`
Name string `json:"name"`
Username string `json:"screen_name"`
Email string `json:"email"`
Data struct {
Id string `json:"id"`
Name string `json:"name"`
Username string `json:"username"`
} `json:"data"`
}
err := json.Unmarshal([]byte(result), &TwitterUserInfo)
@ -239,13 +240,12 @@ func (mg *Maingate) platform_twitter_getuserinfo(token, secret string) (bool, st
// fmt.Println("=====================")
// fmt.Println(result)
// fmt.Println(TwitterUserInfo.Id)
// fmt.Println(TwitterUserInfo.Name)
// fmt.Println(TwitterUserInfo.Username)
// fmt.Println(TwitterUserInfo.Email)
// fmt.Println(TwitterUserInfo.Data.Id)
// fmt.Println(TwitterUserInfo.Data.Name)
// fmt.Println(TwitterUserInfo.Data.Username)
// fmt.Println("=====================")
return true, TwitterUserInfo.Id, TwitterUserInfo.Email
return true, TwitterUserInfo.Data.Id, ""
}
func (mg *Maingate) CallTwitterAPI_WithAPPKey(requesturl, method, nonce string) string {

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,10 @@
package core
import (
"bytes"
"context"
"encoding/hex"
"encoding/json"
"net/http"
"os"
"path"
@ -10,7 +12,7 @@ import (
"time"
"unsafe"
"repositories.action2quare.com/ayo/gocommon"
common "repositories.action2quare.com/ayo/gocommon"
"repositories.action2quare.com/ayo/gocommon/logger"
"go.mongodb.org/mongo-driver/bson"
@ -24,7 +26,7 @@ type authPipelineDocument struct {
DocumentKey struct {
Id primitive.ObjectID `bson:"_id"`
} `bson:"documentKey"`
Authinfo *gocommon.Authinfo `bson:"fullDocument"`
Authinfo *common.Authinfo `bson:"fullDocument"`
}
type servicePipelineDocument struct {
@ -40,7 +42,103 @@ type filePipelineDocument struct {
DocumentKey struct {
Id primitive.ObjectID `bson:"_id"`
} `bson:"documentKey"`
File *FileDocumentDesc `bson:"fullDocument"`
File *fileDocumentDesc `bson:"fullDocument"`
}
type whilelistPipelineDocument struct {
OperationType string `bson:"operationType"`
DocumentKey struct {
Id primitive.ObjectID `bson:"_id"`
} `bson:"documentKey"`
Member *whitelistmember `bson:"fullDocument"`
}
func (mg *Maingate) watchWhitelistCollection(parentctx context.Context) {
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{
"update",
"insert",
}},
}},
},
}}
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 = mg.mongoClient.Watch(CollectionWhitelist, mongo.Pipeline{matchStage, projectStage})
if err != nil {
logger.Error("watchWhitelistCollection watch failed :", err)
time.Sleep(time.Minute)
continue
}
ctx = context.TODO()
}
changed := stream.TryNext(ctx)
if ctx.Err() != nil {
logger.Error("watchWhitelistCollection stream.TryNext failed. process should be restarted! :", ctx.Err().Error())
break
}
if changed {
var data whilelistPipelineDocument
if err := stream.Decode(&data); err == nil {
ot := data.OperationType
switch ot {
case "insert":
// 새 화이트리스트 멤버
mg.service().wl.add(data.Member)
case "update":
if data.Member.Expired != 0 {
logger.Println("whitelist member is removed :", *data.Member)
mg.service().wl.remove(data.Member.Email)
} else {
logger.Println("whitelist member is updated :", *data.Member)
mg.service().wl.add(data.Member)
}
}
} else {
logger.Error("watchWhitelistCollection stream.Decode failed :", err)
}
} else if stream.Err() != nil || stream.ID() == 0 {
select {
case <-ctx.Done():
logger.Println("watchWhitelistCollection is done")
stream.Close(ctx)
return
case <-time.After(time.Second):
logger.Error("watchWhitelistCollection stream error :", stream.Err())
stream.Close(ctx)
stream = nil
}
} else {
time.Sleep(time.Second)
}
}
}
func (mg *Maingate) watchFileCollection(parentctx context.Context, serveMux *http.ServeMux, prefix string) {
@ -115,7 +213,7 @@ func (mg *Maingate) watchFileCollection(parentctx context.Context, serveMux *htt
if err := stream.Decode(&data); err == nil {
switch data.OperationType {
case "insert":
data.File.Save()
data.File.save()
case "delete":
subfolder := hex.EncodeToString(data.DocumentKey.Id[:4])
@ -189,9 +287,11 @@ func (mg *Maingate) watchServiceCollection(parentctx context.Context, serveMux *
logger.Error("service cannot be prepared :", data.Service, err)
} else {
// 내가 임시로 가지고 있던 서비스일 수 있다.
if mg.service().Id == data.Service.Id {
logger.Println("service is on the board! :", data.Service)
atomic.StorePointer(&mg.serviceptr, unsafe.Pointer(data.Service))
already := mg.service().Id == data.Service.Id
logger.Println("service is on the board! :", data.Service)
atomic.StorePointer(&mg.serviceptr, unsafe.Pointer(data.Service))
if !already {
serveMux.Handle(common.MakeHttpHandlerPattern(prefix, data.Service.ServiceCode, "/"), mg.service())
}
}
@ -200,7 +300,33 @@ func (mg *Maingate) watchServiceCollection(parentctx context.Context, serveMux *
case "update":
data.Service.prepare(mg)
atomic.StorePointer(&mg.serviceptr, unsafe.Pointer(data.Service))
old := mg.service()
atomic.SwapPointer(&old.divisionsForUsersSerialized, data.Service.divisionsForUsersSerialized)
atomic.SwapPointer(&old.divisionsSerialized, data.Service.divisionsSerialized)
atomic.SwapPointer(&old.admins, data.Service.admins)
atomic.SwapPointer(&old.serviceSerialized, data.Service.serviceSerialized)
atomic.SwapPointer(&old.serviceSummarySerialized, data.Service.serviceSummarySerialized)
atomic.SwapPointer(&old.wl.emailptr, data.Service.wl.emailptr)
old.Divisions = data.Service.Divisions
for _, div := range old.Divisions {
var req *http.Request
if div.State == DivisionState_FullOpen {
req, _ = http.NewRequest("POST", div.Url+"/maingate", nil)
} else if div.Maintenance != nil {
bt, _ := json.Marshal(div.Maintenance)
req, _ = http.NewRequest("POST", div.Url+"/maingate", bytes.NewBuffer(bt))
}
if req != nil {
// MG-X-API-TOKEN
req.Header.Add("MG-X-API-TOKEN", old.ServerApiTokens[0].Hex())
if resp, err := http.DefaultClient.Do(req); err == nil {
resp.Body.Close()
}
}
}
}
} else {
logger.Error("watchServiceCollection stream.Decode failed :", err)
@ -223,7 +349,7 @@ func (mg *Maingate) watchServiceCollection(parentctx context.Context, serveMux *
}
}
func watchAuthCollection(parentctx context.Context, ac *gocommon.AuthCollection, mongoClient gocommon.MongoClient) {
func watchAuthCollection(parentctx context.Context, ac *common.AuthCollection, mongoClient common.MongoClient) {
defer func() {
s := recover()
if s != nil {

537
fba/js.js

File diff suppressed because one or more lines are too long

View File

@ -1,11 +0,0 @@
<!DOCTYPE html>
<html>
<body>
<script type="text/javascript" src="./fb-ga.min.js">
</script>
</body>
</html>
<!-- <body> -->
<!-- <body onload="window.FBA.TrackLogEvent('DESKTOP-TEST');"> -->
<!-- <script type="cjs" src="./fb-ga.rollup.js"> -->

4
go.mod
View File

@ -1,13 +1,13 @@
module repositories.action2quare.com/ayo/maingate
go 1.18
go 1.19
require (
firebase.google.com/go v3.13.0+incompatible
github.com/golang-jwt/jwt v3.2.2+incompatible
go.mongodb.org/mongo-driver v1.11.7
google.golang.org/api v0.128.0
repositories.action2quare.com/ayo/gocommon v0.0.0-20240205060841-c31f838ba8a9
repositories.action2quare.com/ayo/gocommon v0.0.0-20230621052811-06ef97f11d22
)
require (

55
go.sum
View File

@ -2,16 +2,24 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.110.2 h1:sdFPBr6xG9/wkBbfhmUz/JmZC7X6LavQgcrVINrKiVA=
cloud.google.com/go v0.110.2/go.mod h1:k04UEeEtb6ZBRTv3dZz4CeJC3jKGxyhl0sAiVVquxiw=
cloud.google.com/go/compute v1.19.0 h1:+9zda3WGgW1ZSTlVppLCYFIr48Pa35q1uG2N1itbCEQ=
cloud.google.com/go/compute v1.19.0/go.mod h1:rikpw2y+UMidAe9tISo04EHNOIf42RLYF/q8Bs93scU=
cloud.google.com/go/compute v1.20.1 h1:6aKEtlUiwEpJzM001l0yFkpXmUVXaN8W+fbkb2AZNbg=
cloud.google.com/go/compute v1.20.1/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM=
cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
cloud.google.com/go/firestore v1.10.0 h1:FG5C49ukKKqyljY+XNRZGae1HZaiVe7aoqi2BipnBuM=
cloud.google.com/go/firestore v1.10.0/go.mod h1:eAeoQCV8F35Mcy4k8ZrQbcSYZOayIwoiU7ZJ6xzH1+o=
cloud.google.com/go/iam v0.13.0 h1:+CmB+K0J/33d0zSQ9SlFWUeCCEn5XJA0ZMZ3pHE9u8k=
cloud.google.com/go/iam v0.13.0/go.mod h1:ljOg+rcNfzZ5d6f1nAUJ8ZIxOaZUVoS14bKCtaLZ/D0=
cloud.google.com/go/iam v1.1.1 h1:lW7fzj15aVIXYHREOqjRBV9PsH0Z6u8Y46a1YGvQP4Y=
cloud.google.com/go/iam v1.1.1/go.mod h1:A5avdyVL2tCppe4unb0951eI9jreack+RJ0/d+KUZOU=
cloud.google.com/go/longrunning v0.4.2 h1:WDKiiNXFTaQ6qz/G8FCOkuY9kJmOJGY67wPUC1M2RbE=
cloud.google.com/go/longrunning v0.4.2/go.mod h1:OHrnaYyLUV6oqwh0xiS7e5sLQhP1m0QU9R+WhGDMgIQ=
cloud.google.com/go/longrunning v0.5.1 h1:Fr7TXftcqTudoyRJa113hyaqlGdiBQkp0Gq7tErFDWI=
cloud.google.com/go/longrunning v0.5.1/go.mod h1:spvimkwdz6SPWKEt/XBij79E9fiTkHSQl/fRUUQJYJc=
cloud.google.com/go/storage v1.29.0 h1:6weCgzRvMg7lzuUurI4697AqIRPU1SvzHhynwpW31jI=
cloud.google.com/go/storage v1.29.0/go.mod h1:4puEjyTKnku6gfKoTfNOU/W+a9JyuVNxjpS5GBrB8h4=
cloud.google.com/go/storage v1.30.1 h1:uOdMxAs8HExqBlnLtnQyP0YkvbiDpdGShGKtx6U/oNM=
cloud.google.com/go/storage v1.30.1/go.mod h1:NfxhC0UJE1aXSx7CIIbCf7y9HKT7BiccwkR7+P7gN8E=
firebase.google.com/go v3.13.0+incompatible h1:3TdYC3DDi6aHn20qoRkxwGqNgdjtblwVAyRLQwGn/+4=
@ -86,11 +94,16 @@ github.com/google/s2a-go v0.1.4/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkj
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/enterprise-certificate-proxy v0.2.3 h1:yk9/cqRKtT9wXZSsRH9aurXEpJX+U6FLtpYTdC3R06k=
github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k=
github.com/googleapis/enterprise-certificate-proxy v0.2.5 h1:UR4rDjcgpgEnqpIEvkiqTYKBCKLNmlge2eVjoZfySzM=
github.com/googleapis/enterprise-certificate-proxy v0.2.5/go.mod h1:RxW0N9901Cko1VOCW3SXCpWP+mlIEkk2tP7jnHy9a3w=
github.com/googleapis/gax-go/v2 v2.8.0 h1:UBtEZqx1bjXtOQ5BVTkuYghXrr3N4V123VKJK67vJZc=
github.com/googleapis/gax-go/v2 v2.8.0/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI=
github.com/googleapis/gax-go/v2 v2.11.0 h1:9V9PWXEsWnPpQhu/PeQIkS4eGzMlTLGgt80cUUI8Ki4=
github.com/googleapis/gax-go/v2 v2.11.0/go.mod h1:DxmR61SGKkGLa2xigwuZIQpkCI2S5iydzRfb3peWZJI=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc=
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/klauspost/compress v1.16.6 h1:91SKEy4K37vkp255cJ8QesJhjyRO0hn9i9G0GoUwLsk=
github.com/klauspost/compress v1.16.6/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
@ -99,6 +112,7 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6fbMZ9s0scYfZQ84/6SPL6zC8ACM2oIL0=
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE=
github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
@ -127,16 +141,21 @@ github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
github.com/xdg-go/scram v1.1.1 h1:VOMT+81stJgXW3CpHyqHN3AXDYIMsx56mEFrB37Mb/E=
github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g=
github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY=
github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4=
github.com/xdg-go/stringprep v1.0.3 h1:kdwGpVNwPFtjs98xCGkHjQtGKh86rDcRZN17QEMCOIs=
github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8=
github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8=
github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA=
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a h1:fZHgsYlfvtyqToslyjUt3VOPF4J7aK/3MPcK7xp3PDk=
github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a/go.mod h1:ul22v+Nro/R083muKhosV54bj5niojjWZvU8xrevuH4=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.mongodb.org/mongo-driver v1.11.6 h1:XM7G6PjiGAO5betLF13BIa5TlLUUE3uJ/2Ox3Lz1K+o=
go.mongodb.org/mongo-driver v1.11.6/go.mod h1:G9TgswdsWjX4tmDA5zfs2+6AEPpYJwqblyjsfuh8oXY=
go.mongodb.org/mongo-driver v1.11.7 h1:LIwYxASDLGUg/8wOhgOOZhX8tQa/9tgZPgzZoVqJvcs=
go.mongodb.org/mongo-driver v1.11.7/go.mod h1:G9TgswdsWjX4tmDA5zfs2+6AEPpYJwqblyjsfuh8oXY=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
@ -148,6 +167,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g=
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM=
golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@ -168,10 +189,14 @@ golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwY
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.11.0 h1:Gi2tvZIJyBtO9SDr1q9h5hEQCp/4L2RQ+ar0qjx2oNU=
golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8=
golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE=
golang.org/x/oauth2 v0.9.0 h1:BPpt2kU7oMRq3kCHAA1tbSEshXRw1LpG2ztgDwrzuAs=
golang.org/x/oauth2 v0.9.0/go.mod h1:qYgFZaFiu6Wg24azG8bdV52QJXJGbZzIIsRCdVKzbLw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -180,6 +205,8 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI=
golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -192,6 +219,8 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s=
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
@ -202,6 +231,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.10.0 h1:UpjohKhiEgNc0CSauXmwYftY1+LlaC75SJwh0SgCX58=
golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
@ -218,6 +249,8 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk=
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
google.golang.org/api v0.123.0 h1:yHVU//vA+qkOhm4reEC9LtzHVUCN/IqqNRl1iQ9xE20=
google.golang.org/api v0.123.0/go.mod h1:gcitW0lvnyWjSp9nKxAbdHKIZ6vF4aajGueeslZOyms=
google.golang.org/api v0.128.0 h1:RjPESny5CnQRn9V6siglged+DZCgfu9l6mO9dkX9VOg=
google.golang.org/api v0.128.0/go.mod h1:Y611qgqaE92On/7g65MQgxYul3c0rEB894kniWLY750=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
@ -228,6 +261,8 @@ google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoA
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A=
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU=
google.golang.org/genproto v0.0.0-20230530153820-e85fd2cbaebc h1:8DyZCyvI8mE1IdLy/60bS+52xfymkE72wv1asokgtao=
google.golang.org/genproto v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:xZnkP7mREFX5MORlOPEzLMr+90PPZQ2QWzrVTWfAq64=
google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc h1:kVKPf/IiYSBWEWtkIn6wZXwWGCnLKcC8oWfZvXjsGnM=
@ -242,6 +277,8 @@ google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTp
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
google.golang.org/grpc v1.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag=
google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8=
google.golang.org/grpc v1.56.0 h1:+y7Bs8rtMd07LeXmL3NxcTLn7mUkbKZqEpPhMNkwJEE=
google.golang.org/grpc v1.56.0/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
@ -268,7 +305,17 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
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-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/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=
repositories.action2quare.com/ayo/gocommon v0.0.0-20230612013915-5950ff4bb82e h1:m0jo1r+2NtBfxwj92e6EVaBZpzTDT6Hq7D93vWO4h9Y=
repositories.action2quare.com/ayo/gocommon v0.0.0-20230612013915-5950ff4bb82e/go.mod h1:ng62uGMGXyQSeuxePG5gJAMtip4Rnspu5Tu7hgvaXns=
repositories.action2quare.com/ayo/gocommon v0.0.0-20230614091557-9b877d9a732c h1:fhCuu0jFps8T1sN8hO0fGnatvNDW6VwM96PV26EA3T4=
repositories.action2quare.com/ayo/gocommon v0.0.0-20230614091557-9b877d9a732c/go.mod h1:ng62uGMGXyQSeuxePG5gJAMtip4Rnspu5Tu7hgvaXns=
repositories.action2quare.com/ayo/gocommon v0.0.0-20230616031450-0b2c9351a717 h1:WrkkEWN3bh1QAulNJZjAiwXx2aPAj39OoIyJFUXmDaE=
repositories.action2quare.com/ayo/gocommon v0.0.0-20230616031450-0b2c9351a717/go.mod h1:ng62uGMGXyQSeuxePG5gJAMtip4Rnspu5Tu7hgvaXns=
repositories.action2quare.com/ayo/gocommon v0.0.0-20230616032216-378bc19f3742 h1:qEbzwVDz1w2ewNHu+vipzV+a804wmwRWe+0vnhCbJr4=
repositories.action2quare.com/ayo/gocommon v0.0.0-20230616032216-378bc19f3742/go.mod h1:ng62uGMGXyQSeuxePG5gJAMtip4Rnspu5Tu7hgvaXns=
repositories.action2quare.com/ayo/gocommon v0.0.0-20230620005911-15ba3e93d621 h1:9Hzdn13l9U0RJn9mMXsZQr+jsmsgy3zQFsBHPSOJnxM=
repositories.action2quare.com/ayo/gocommon v0.0.0-20230620005911-15ba3e93d621/go.mod h1:ng62uGMGXyQSeuxePG5gJAMtip4Rnspu5Tu7hgvaXns=
repositories.action2quare.com/ayo/gocommon v0.0.0-20230621051330-0d8752e66161 h1:sgixcFwdLOqcvwqTaKcsMEepXsLmNEgaybyur3QHRgk=
repositories.action2quare.com/ayo/gocommon v0.0.0-20230621051330-0d8752e66161/go.mod h1:ng62uGMGXyQSeuxePG5gJAMtip4Rnspu5Tu7hgvaXns=
repositories.action2quare.com/ayo/gocommon v0.0.0-20230621052811-06ef97f11d22 h1:DImSGNxZrc+Q4WlS1OKMsLAScEfDYLX4XMJdjAaVnXc=
repositories.action2quare.com/ayo/gocommon v0.0.0-20230621052811-06ef97f11d22/go.mod h1:ng62uGMGXyQSeuxePG5gJAMtip4Rnspu5Tu7hgvaXns=

View File

@ -6,7 +6,7 @@ import (
"net/http"
"time"
"repositories.action2quare.com/ayo/gocommon"
common "repositories.action2quare.com/ayo/gocommon"
"repositories.action2quare.com/ayo/gocommon/flagx"
"repositories.action2quare.com/ayo/gocommon/logger"
"repositories.action2quare.com/ayo/maingate/core"
@ -36,7 +36,7 @@ func main() {
panic(err)
}
server := gocommon.NewHTTPServer(serveMux)
server := common.NewHTTPServer(serveMux)
logger.Println("maingate is started")
if err := server.Start(); err != nil {
logger.Error("maingate is stopped with error :", err)

View File

@ -4,11 +4,27 @@ $CurBranch = git branch --show-current
Remove-Item maingate.zip -Force -Recurse -ErrorAction SilentlyContinue
cd ..
cd maingate-console
git switch $CurBranch
git pull
npm install
npm run build
Remove-Item console -Force -Recurse -ErrorAction SilentlyContinue
Copy-Item build console -Recurse
Compress-Archive -Path console -DestinationPath ..\maingate\maingate.zip -Force
Remove-Item console -Force -Recurse
cd ..
cd maingate
$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

File diff suppressed because one or more lines are too long