Compare commits
132 Commits
6aa35ffc4f
...
kd-live
| Author | SHA1 | Date | |
|---|---|---|---|
| 2d060fe117 | |||
| 231b1a35d5 | |||
| 845784d204 | |||
| 424c8be420 | |||
| ce39e8d878 | |||
| 54c727117b | |||
| 7816fd56c0 | |||
| 564a2ee14a | |||
| cbcae00c77 | |||
| 28dc84769d | |||
| 0c678947cd | |||
| dbd0a7bf5f | |||
| 86247e053d | |||
| 757c6d312c | |||
| e37a974d9c | |||
| 470591cb44 | |||
| 38114769b3 | |||
| b05473a1c6 | |||
| 0fff694e8a | |||
| d8713298c4 | |||
| 763b0fc4bd | |||
| d8e18d7ffc | |||
| 381f1edb80 | |||
| a8e448b8ca | |||
| 9b0e3a5d5b | |||
| 5757a81cb8 | |||
| c4b8e630dc | |||
| 43b0242652 | |||
| 893744a1ab | |||
| 192cc569b4 | |||
| 56e6608537 | |||
| 0053033e32 | |||
| d1ff6a56fc | |||
| 114461c51d | |||
| 117a3e5d90 | |||
| fafc463f2a | |||
| e2bec481f0 | |||
| 89e7d35b5a | |||
| fe662c5355 | |||
| 6767a37704 | |||
| 2ea035a43b | |||
| 2a1ad499ed | |||
| 5cc6ddc8f1 | |||
| 0e070221f8 | |||
| 1ba32aa4c9 | |||
| edb3e07329 | |||
| f5304fae80 | |||
| d9be04541b | |||
| d2e06961b9 | |||
| 28092fcf17 | |||
| a7a20aebcf | |||
| c43c10982c | |||
| 02c4f9e3d1 | |||
| 1db22730aa | |||
| 184675a9b7 | |||
| 197ee7127b | |||
| 869fa48d74 | |||
| 7470f8e001 | |||
| fc70a9482c | |||
| e3afb58634 | |||
| bafb67dabc | |||
| 9ccd97564a | |||
| 08cb989975 | |||
| 455011fd99 | |||
| 4958cb0b93 | |||
| e8832f329a | |||
| 9c14480be7 | |||
| daf3e3f027 | |||
| a8df7d54bd | |||
| 2de82b9d2a | |||
| 00c2d6e205 | |||
| 87d922c558 | |||
| 0be7adefe3 | |||
| 3a9f81f1cb | |||
| 39e1b925e5 | |||
| a97b9f0983 | |||
| 42b4ade782 | |||
| 9edea29983 | |||
| c7f073c779 | |||
| 8e908982a8 | |||
| 8126406e5f | |||
| 6b68d918ba | |||
| fb5db25dce | |||
| f79e922fa0 | |||
| 3216e2620a | |||
| d796958d5e | |||
| f66904d428 | |||
| 22ec115b35 | |||
| 8d70777269 | |||
| 15ead6b0bc | |||
| 5abb3fd2b7 | |||
| 97636ce31d | |||
| ed85918e7f | |||
| c5ec99d3e1 | |||
| 2b4becdb61 | |||
| 4af93b3d7e | |||
| 429bbd1e7a | |||
| afc3a10f51 | |||
| 1c397da77a | |||
| 3834ca2e37 | |||
| 0898213aa8 | |||
| 5502c4d744 | |||
| cb08ecb53a | |||
| cb793092e9 | |||
| 70d775e0fc | |||
| 13f6492e5f | |||
| 92c5bf5b46 | |||
| f739eb3a8b | |||
| 6eed2be7f4 | |||
| c95d7747cd | |||
| 31782578f4 | |||
| 841dad4992 | |||
| 265ae0ac8b | |||
| ff7d56152e | |||
| cd126d2c59 | |||
| 2acca6dbe8 | |||
| d3332f530f | |||
| 484db90037 | |||
| b06eb86578 | |||
| 9704decb7a | |||
| 767d6bf002 | |||
| 79e00de9f6 | |||
| 1f7421dd2e | |||
| 7e5da4948c | |||
| 53701d61f8 | |||
| 6d02eb092c | |||
| 21d4080baa | |||
| 7bee78a875 | |||
| 2cd2a20065 | |||
| 74c0a215ed | |||
| e65fbafd36 | |||
| f0f5011e10 |
37
backup/firebase-jssdk/fb-ga.js
Normal file
37
backup/firebase-jssdk/fb-ga.js
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
// 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]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
1
backup/firebase-jssdk/fb-ga.min.js
vendored
Normal file
1
backup/firebase-jssdk/fb-ga.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
2376
backup/firebase-jssdk/fb-ga.rollup.js
Normal file
2376
backup/firebase-jssdk/fb-ga.rollup.js
Normal file
File diff suppressed because one or more lines are too long
3
backup/firebase-jssdk/firebase-analytics.js
Normal file
3
backup/firebase-jssdk/firebase-analytics.js
Normal file
File diff suppressed because one or more lines are too long
2522
backup/firebase-jssdk/firebase-app.js
Normal file
2522
backup/firebase-jssdk/firebase-app.js
Normal file
File diff suppressed because it is too large
Load Diff
537
backup/firebase-jssdk/js.js
Normal file
537
backup/firebase-jssdk/js.js
Normal file
File diff suppressed because one or more lines are too long
3
backup/firebase-jssdk/original/firebase-analytics.js
Normal file
3
backup/firebase-jssdk/original/firebase-analytics.js
Normal file
File diff suppressed because one or more lines are too long
2522
backup/firebase-jssdk/original/firebase-app.js
Normal file
2522
backup/firebase-jssdk/original/firebase-app.js
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,8 @@
|
|||||||
{
|
{
|
||||||
"maingate_mongodb_url": "mongodb://...",
|
"maingate_mongodb_url": "mongodb://...",
|
||||||
"autologin_ttl": 604800,
|
"autologin_ttl": 604800,
|
||||||
|
"acc_del_ttl": 7776000,
|
||||||
|
"maximum_num_link_account": 10,
|
||||||
"redirect_base_url": "",
|
"redirect_base_url": "",
|
||||||
"google_client_id" : "",
|
"google_client_id" : "",
|
||||||
"google_client_secret" : "",
|
"google_client_secret" : "",
|
||||||
@ -24,6 +26,15 @@
|
|||||||
|
|
||||||
"firebase_admin_sdk_credentialfile": "",
|
"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" : [
|
"maingate_global_admins" : [
|
||||||
"mountain@action2quare.com"
|
"mountain@action2quare.com"
|
||||||
]
|
]
|
||||||
|
|||||||
351
core/api.go
351
core/api.go
@ -2,9 +2,7 @@ package core
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/md5"
|
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/hex"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -18,7 +16,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
common "repositories.action2quare.com/ayo/gocommon"
|
"repositories.action2quare.com/ayo/gocommon"
|
||||||
"repositories.action2quare.com/ayo/gocommon/logger"
|
"repositories.action2quare.com/ayo/gocommon/logger"
|
||||||
|
|
||||||
"go.mongodb.org/mongo-driver/bson"
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
@ -26,8 +24,7 @@ import (
|
|||||||
"go.mongodb.org/mongo-driver/mongo/options"
|
"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"`
|
Key string `bson:"key" json:"key"`
|
||||||
Src string `bson:"src" json:"src"`
|
Src string `bson:"src" json:"src"`
|
||||||
Link string `bson:"link" json:"link"`
|
Link string `bson:"link" json:"link"`
|
||||||
@ -37,7 +34,7 @@ type fileDocumentDesc struct {
|
|||||||
Contents []byte `bson:"contents,omitempty" json:"contents,omitempty"`
|
Contents []byte `bson:"contents,omitempty" json:"contents,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fd *fileDocumentDesc) save() error {
|
func (fd *FileDocumentDesc) Save() error {
|
||||||
// 새 파일 올라옴
|
// 새 파일 올라옴
|
||||||
if len(fd.Contents) == 0 {
|
if len(fd.Contents) == 0 {
|
||||||
return nil
|
return nil
|
||||||
@ -66,48 +63,16 @@ func (fd *fileDocumentDesc) save() error {
|
|||||||
if fd.Extract {
|
if fd.Extract {
|
||||||
switch path.Ext(destFile) {
|
switch path.Ext(destFile) {
|
||||||
case ".zip":
|
case ".zip":
|
||||||
err = common.Unzip(destFile)
|
err = gocommon.Unzip(destFile)
|
||||||
case ".tar":
|
case ".tar":
|
||||||
err = common.Untar(destFile)
|
err = gocommon.Untar(destFile)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return err
|
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 {
|
func (caller apiCaller) filesAPI(w http.ResponseWriter, r *http.Request) error {
|
||||||
if r.Method == "GET" {
|
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{
|
allfiles, err := caller.mg.mongoClient.All(CollectionFile, options.Find().SetProjection(bson.M{
|
||||||
"contents": 0,
|
"contents": 0,
|
||||||
}).SetReturnKey(false))
|
}).SetReturnKey(false))
|
||||||
@ -126,11 +91,6 @@ func (caller apiCaller) filesAPI(w http.ResponseWriter, r *http.Request) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// if !caller.isAdminOrValidToken() {
|
|
||||||
// w.WriteHeader(http.StatusUnauthorized)
|
|
||||||
// return nil
|
|
||||||
// }
|
|
||||||
|
|
||||||
_, err := caller.mg.mongoClient.Delete(CollectionFile, bson.M{
|
_, err := caller.mg.mongoClient.Delete(CollectionFile, bson.M{
|
||||||
"key": key,
|
"key": key,
|
||||||
})
|
})
|
||||||
@ -147,11 +107,6 @@ var seq = uint32(0)
|
|||||||
|
|
||||||
func (caller apiCaller) uploadAPI(w http.ResponseWriter, r *http.Request) error {
|
func (caller apiCaller) uploadAPI(w http.ResponseWriter, r *http.Request) error {
|
||||||
if r.Method == "PUT" {
|
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")
|
infile, header, err := r.FormFile("file")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
@ -167,20 +122,19 @@ func (caller apiCaller) uploadAPI(w http.ResponseWriter, r *http.Request) error
|
|||||||
var b [5]byte
|
var b [5]byte
|
||||||
binary.BigEndian.PutUint32(b[0:4], uint32(time.Now().Unix()))
|
binary.BigEndian.PutUint32(b[0:4], uint32(time.Now().Unix()))
|
||||||
b[4] = byte(atomic.AddUint32(&seq, 1) % 255)
|
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[:], newidbt[:8])
|
|
||||||
|
|
||||||
|
newidobj := primitive.NewObjectID()
|
||||||
|
copy(newidobj[:], b[1:])
|
||||||
|
|
||||||
|
rf := newidobj.Hex()
|
||||||
var link string
|
var link string
|
||||||
if extract {
|
if extract {
|
||||||
link = path.Join("static", subfolder, rf)
|
link = path.Join("static", rf)
|
||||||
} else {
|
} else {
|
||||||
link = path.Join("static", subfolder, rf, header.Filename)
|
link = path.Join("static", rf, header.Filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
newdoc := fileDocumentDesc{
|
newdoc := FileDocumentDesc{
|
||||||
Contents: contents,
|
Contents: contents,
|
||||||
Src: header.Filename,
|
Src: header.Filename,
|
||||||
Timestamp: time.Now().UTC().Unix(),
|
Timestamp: time.Now().UTC().Unix(),
|
||||||
@ -188,12 +142,10 @@ func (caller apiCaller) uploadAPI(w http.ResponseWriter, r *http.Request) error
|
|||||||
Link: link,
|
Link: link,
|
||||||
Desc: desc,
|
Desc: desc,
|
||||||
Key: rf,
|
Key: rf,
|
||||||
Service: servicename,
|
|
||||||
}
|
}
|
||||||
_, _, err = caller.mg.mongoClient.UpsertOne(CollectionFile, bson.M{
|
_, _, err = caller.mg.mongoClient.UpsertOne(CollectionFile, bson.M{
|
||||||
"_id": newidobj,
|
"_id": newidobj,
|
||||||
"service": servicename,
|
"key": rf,
|
||||||
"key": rf,
|
|
||||||
}, newdoc)
|
}, newdoc)
|
||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@ -206,46 +158,81 @@ func (caller apiCaller) uploadAPI(w http.ResponseWriter, r *http.Request) error
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (caller apiCaller) whitelistAPI(w http.ResponseWriter, r *http.Request) error {
|
func (caller apiCaller) blockAPI(w http.ResponseWriter, r *http.Request) error {
|
||||||
mg := caller.mg
|
mg := caller.mg
|
||||||
queryvals := r.URL.Query()
|
|
||||||
if r.Method == "GET" {
|
if r.Method == "GET" {
|
||||||
// if !caller.isAdminOrValidToken() {
|
json.NewEncoder(w).Encode(mg.bl.all())
|
||||||
// logger.Println("whitelistAPI failed. not vaild user :", r.Method, caller.userinfo)
|
} else if r.Method == "PUT" {
|
||||||
// w.WriteHeader(http.StatusUnauthorized)
|
body, _ := io.ReadAll(r.Body)
|
||||||
// return nil
|
|
||||||
// }
|
|
||||||
|
|
||||||
all, err := mg.mongoClient.All(CollectionWhitelist)
|
var bipl blockinfoWithStringId
|
||||||
|
if err := json.Unmarshal(body, &bipl); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
accid, err := primitive.ObjectIDFromHex(bipl.StrId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(all) > 0 {
|
bi := blockinfo{
|
||||||
var notexp []primitive.M
|
Start: primitive.NewDateTimeFromTime(time.Unix(bipl.StartUnix, 0)),
|
||||||
for _, v := range all {
|
End: primitive.NewDateTimeFromTime(time.Unix(bipl.EndUnix, 0)),
|
||||||
if _, exp := v["_ts"]; !exp {
|
Reason: bipl.Reason,
|
||||||
notexp = append(notexp, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
allraw, _ := json.Marshal(notexp)
|
|
||||||
w.Write(allraw)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
if r.Method == "GET" {
|
||||||
|
enc := json.NewEncoder(w)
|
||||||
|
enc.Encode(mg.wl.all())
|
||||||
} else if r.Method == "PUT" {
|
} else if r.Method == "PUT" {
|
||||||
body, _ := io.ReadAll(r.Body)
|
body, _ := io.ReadAll(r.Body)
|
||||||
var member whitelistmember
|
var member whitelistmember
|
||||||
if err := json.Unmarshal(body, &member); err != nil {
|
if err := json.Unmarshal(body, &member); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
member.ExpiredAt = 0
|
||||||
// if !caller.isAdminOrValidToken() {
|
member.Id = primitive.NilObjectID
|
||||||
// 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{
|
_, _, err := mg.mongoClient.Update(CollectionWhitelist, bson.M{
|
||||||
"_id": primitive.NewObjectID(),
|
"_id": primitive.NewObjectID(),
|
||||||
}, bson.M{
|
}, bson.M{
|
||||||
@ -256,7 +243,8 @@ func (caller apiCaller) whitelistAPI(w http.ResponseWriter, r *http.Request) err
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else if r.Method == "DELETE" {
|
} else if r.Method == "DELETE" {
|
||||||
id := queryvals.Get("id")
|
id := r.URL.Query().Get("id")
|
||||||
|
|
||||||
if len(id) == 0 {
|
if len(id) == 0 {
|
||||||
return errors.New("id param is missing")
|
return errors.New("id param is missing")
|
||||||
}
|
}
|
||||||
@ -282,20 +270,22 @@ func (caller apiCaller) whitelistAPI(w http.ResponseWriter, r *http.Request) err
|
|||||||
func (caller apiCaller) serviceAPI(w http.ResponseWriter, r *http.Request) error {
|
func (caller apiCaller) serviceAPI(w http.ResponseWriter, r *http.Request) error {
|
||||||
mg := caller.mg
|
mg := caller.mg
|
||||||
if r.Method == "GET" {
|
if r.Method == "GET" {
|
||||||
|
logger.Println("serviceAPI :", r.URL.Path)
|
||||||
if mg.service().Id.IsZero() {
|
if mg.service().Id.IsZero() {
|
||||||
|
logger.Println(" id is zero")
|
||||||
newService := serviceDescription{
|
newService := serviceDescription{
|
||||||
ServiceDescriptionSummary: ServiceDescriptionSummary{
|
ServiceDescriptionSummary: ServiceDescriptionSummary{
|
||||||
Id: primitive.NewObjectID(),
|
Id: primitive.NewObjectID(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
if err := newService.prepare(caller.mg); err != nil {
|
if err := newService.prepare(caller.mg); err != nil {
|
||||||
|
logger.Println(" prepare failed :", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
atomic.StorePointer(&mg.serviceptr, unsafe.Pointer(&newService))
|
atomic.StorePointer(&mg.serviceptr, unsafe.Pointer(&newService))
|
||||||
}
|
}
|
||||||
|
|
||||||
serptr := atomic.LoadPointer(&mg.service().serviceSerialized)
|
w.Write(mg.service().serviceSerialized)
|
||||||
w.Write(*(*[]byte)(serptr))
|
|
||||||
} else if r.Method == "POST" {
|
} else if r.Method == "POST" {
|
||||||
body, _ := io.ReadAll(r.Body)
|
body, _ := io.ReadAll(r.Body)
|
||||||
var service serviceDescription
|
var service serviceDescription
|
||||||
@ -330,8 +320,7 @@ func (caller apiCaller) serviceAPI(w http.ResponseWriter, r *http.Request) error
|
|||||||
func (caller apiCaller) maintenanceAPI(w http.ResponseWriter, r *http.Request) error {
|
func (caller apiCaller) maintenanceAPI(w http.ResponseWriter, r *http.Request) error {
|
||||||
mg := caller.mg
|
mg := caller.mg
|
||||||
if r.Method == "GET" {
|
if r.Method == "GET" {
|
||||||
serptr := atomic.LoadPointer(&mg.service().divisionsSerialized)
|
w.Write(mg.service().divisionsSerialized)
|
||||||
w.Write(*(*[]byte)(serptr))
|
|
||||||
} else if r.Method == "POST" {
|
} else if r.Method == "POST" {
|
||||||
var divs map[string]*Division
|
var divs map[string]*Division
|
||||||
dec := json.NewDecoder(r.Body)
|
dec := json.NewDecoder(r.Body)
|
||||||
@ -355,20 +344,94 @@ func (caller apiCaller) maintenanceAPI(w http.ResponseWriter, r *http.Request) e
|
|||||||
return nil
|
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")
|
var errApiTokenMissing = errors.New("mg-x-api-token is missing")
|
||||||
|
|
||||||
func (caller apiCaller) configAPI(w http.ResponseWriter, r *http.Request) error {
|
func (caller apiCaller) configAPI(w http.ResponseWriter, r *http.Request) error {
|
||||||
mg := caller.mg
|
mg := caller.mg
|
||||||
apitoken := r.Header.Get("MG-X-API-TOKEN")
|
|
||||||
if len(apitoken) == 0 {
|
if !*devflag {
|
||||||
return errApiTokenMissing
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
apitokenObj, _ := primitive.ObjectIDFromHex(apitoken)
|
return nil
|
||||||
if !mg.service().isValidToken(apitokenObj) {
|
}
|
||||||
return fmt.Errorf("mg-x-api-token is not valid : %s", apitoken)
|
|
||||||
|
func (caller apiCaller) lockcreatecharAPI(w http.ResponseWriter, r *http.Request) error {
|
||||||
|
mg, err := caller.mg.mongoClient.FindAll(CollectionService, bson.M{})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
haschr, _ := gocommon.ReadStringFormValue(r.Form, "haschr")
|
||||||
|
|
||||||
|
locked := make(map[string]any)
|
||||||
|
if haschr == "true" {
|
||||||
|
locked["lock"] = false
|
||||||
|
} else {
|
||||||
|
curregion, _ := gocommon.ReadStringFormValue(r.Form, "region")
|
||||||
|
|
||||||
|
for _, regioninfo := range mg {
|
||||||
|
region := regioninfo["divisions"].(primitive.M)
|
||||||
|
for idx, rl := range region {
|
||||||
|
if idx == curregion {
|
||||||
|
if rl.(primitive.M)["lockcreatechar"].(bool) {
|
||||||
|
locked["lock"] = true
|
||||||
|
} else {
|
||||||
|
locked["lock"] = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
create, _ := json.Marshal(locked)
|
||||||
|
w.Write(create)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -392,63 +455,71 @@ func (mg *Maingate) api(w http.ResponseWriter, r *http.Request) {
|
|||||||
r.Body.Close()
|
r.Body.Close()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
r.ParseMultipartForm(32 << 20)
|
||||||
|
|
||||||
var userinfo map[string]any
|
var userinfo map[string]any
|
||||||
|
|
||||||
if !*noauth {
|
var apiTokenObj primitive.ObjectID
|
||||||
authheader := r.Header.Get("Authorization")
|
if !*devflag {
|
||||||
if len(authheader) == 0 {
|
apiToken := r.Header.Get("MG-X-API-TOKEN")
|
||||||
logger.Println("Authorization header is not valid :", authheader)
|
if len(apiToken) > 0 {
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
if apiToken != mg.maingateConfig.ApiToken {
|
||||||
return
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
}
|
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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr := atomic.LoadPointer(&mg.admins)
|
ptr := atomic.LoadPointer(&mg.admins)
|
||||||
adminsptr := (*globalAdmins)(ptr)
|
adminsptr := (*globalAdmins)(ptr)
|
||||||
|
|
||||||
if adminsptr.modtime != common.ConfigModTime() {
|
if adminsptr.modtime != gocommon.ConfigModTime() {
|
||||||
var config globalAdmins
|
var config globalAdmins
|
||||||
if err := common.LoadConfig(&config); err == nil {
|
if err := gocommon.LoadConfig(&config); err == nil {
|
||||||
config.parse()
|
config.parse()
|
||||||
adminsptr = &config
|
adminsptr = &config
|
||||||
atomic.StorePointer(&mg.admins, unsafe.Pointer(adminsptr))
|
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)
|
logger.Println("api call :", r.URL.Path, r.Method, r.URL.Query(), userinfo)
|
||||||
caller := apiCaller{
|
caller := apiCaller{
|
||||||
userinfo: userinfo,
|
userinfo: userinfo,
|
||||||
@ -470,6 +541,12 @@ func (mg *Maingate) api(w http.ResponseWriter, r *http.Request) {
|
|||||||
err = caller.maintenanceAPI(w, r)
|
err = caller.maintenanceAPI(w, r)
|
||||||
} else if strings.HasSuffix(r.URL.Path, "/files") {
|
} else if strings.HasSuffix(r.URL.Path, "/files") {
|
||||||
err = caller.filesAPI(w, r)
|
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 {
|
if err != nil {
|
||||||
|
|||||||
407
core/api_coupon.go
Normal file
407
core/api_coupon.go
Normal file
@ -0,0 +1,407 @@
|
|||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
39
core/api_test.go
Normal file
39
core/api_test.go
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
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))
|
||||||
|
}
|
||||||
354
core/maingate.go
354
core/maingate.go
@ -10,14 +10,17 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"math/big"
|
"math/big"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"runtime/debug"
|
||||||
"strings"
|
"strings"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
"text/template"
|
||||||
"time"
|
"time"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
common "repositories.action2quare.com/ayo/gocommon"
|
"repositories.action2quare.com/ayo/gocommon"
|
||||||
"repositories.action2quare.com/ayo/gocommon/flagx"
|
"repositories.action2quare.com/ayo/gocommon/flagx"
|
||||||
"repositories.action2quare.com/ayo/gocommon/logger"
|
"repositories.action2quare.com/ayo/gocommon/logger"
|
||||||
|
|
||||||
@ -36,20 +39,21 @@ var devflag = flagx.Bool("dev", false, "")
|
|||||||
var noauth = flagx.Bool("noauth", false, "")
|
var noauth = flagx.Bool("noauth", false, "")
|
||||||
|
|
||||||
var (
|
var (
|
||||||
CollectionLink = common.CollectionName("link")
|
CollectionLink = gocommon.CollectionName("link")
|
||||||
CollectionAuth = common.CollectionName("auth")
|
CollectionAuth = gocommon.CollectionName("auth")
|
||||||
CollectionWhitelist = common.CollectionName("whitelist")
|
CollectionWhitelist = gocommon.CollectionName("whitelist")
|
||||||
CollectionService = common.CollectionName("service")
|
CollectionService = gocommon.CollectionName("service")
|
||||||
CollectionAccount = common.CollectionName("account")
|
CollectionAccount = gocommon.CollectionName("account")
|
||||||
CollectionFile = common.CollectionName("file")
|
CollectionFile = gocommon.CollectionName("file")
|
||||||
CollectionBlock = common.CollectionName("block")
|
CollectionBlock = gocommon.CollectionName("block")
|
||||||
CollectionPlatformLoginToken = common.CollectionName("platform_login_token") //-- 각 플랫폼에 로그인 및 권한 받아오는 과정에 사용하는 Key
|
CollectionPlatformLoginToken = gocommon.CollectionName("platform_login_token") //-- 각 플랫폼에 로그인 및 권한 받아오는 과정에 사용하는 Key
|
||||||
CollectionUserToken = common.CollectionName("usertoken")
|
CollectionUserToken = gocommon.CollectionName("usertoken")
|
||||||
CollectionGamepotUserInfo = common.CollectionName("gamepot_userinfo") //-- 클라로부터 수집된 gamepot 정보 - server to server로 유효성이 검증되진 않았지만 수집은 한다.
|
CollectionGamepotUserInfo = gocommon.CollectionName("gamepot_userinfo") //-- 클라로부터 수집된 gamepot 정보 - server to server로 유효성이 검증되진 않았지만 수집은 한다.
|
||||||
CollectionFirebaseUserInfo = common.CollectionName("firebase_userinfo") //-- Firebase UserInfo
|
CollectionFirebaseUserInfo = gocommon.CollectionName("firebase_userinfo") //-- Firebase UserInfo
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
AuthPlatformSteamSDK = "steam"
|
||||||
AuthPlatformFirebaseAuth = "firebase"
|
AuthPlatformFirebaseAuth = "firebase"
|
||||||
AuthPlatformGoogle = "google"
|
AuthPlatformGoogle = "google"
|
||||||
AuthPlatformMicrosoft = "microsoft"
|
AuthPlatformMicrosoft = "microsoft"
|
||||||
@ -71,10 +75,10 @@ func SessionTTL() time.Duration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type mongoAuthCell struct {
|
type mongoAuthCell struct {
|
||||||
src *common.Authinfo
|
src *gocommon.Authinfo
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ac *mongoAuthCell) ToAuthinfo() *common.Authinfo {
|
func (ac *mongoAuthCell) ToAuthinfo() *gocommon.Authinfo {
|
||||||
if ac.src == nil {
|
if ac.src == nil {
|
||||||
logger.Error("mongoAuthCell ToAuthinfo failed. ac.src is nil")
|
logger.Error("mongoAuthCell ToAuthinfo failed. ac.src is nil")
|
||||||
}
|
}
|
||||||
@ -86,15 +90,15 @@ func (ac *mongoAuthCell) ToBytes() []byte {
|
|||||||
return bt
|
return bt
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeAuthCollection(mongoClient common.MongoClient, sessionTTL time.Duration) *common.AuthCollection {
|
func makeAuthCollection(mongoClient gocommon.MongoClient, sessionTTL time.Duration) *gocommon.AuthCollection {
|
||||||
authcoll := common.MakeAuthCollection(sessionTTL)
|
authcoll := gocommon.MakeAuthCollection(sessionTTL)
|
||||||
authcoll.SessionRemoved = func(sk string) {
|
authcoll.SessionRemoved = func(sk string) {
|
||||||
skid, _ := primitive.ObjectIDFromHex(sk)
|
skid, _ := primitive.ObjectIDFromHex(sk)
|
||||||
mongoClient.Delete(CollectionAuth, bson.M{
|
mongoClient.Delete(CollectionAuth, bson.M{
|
||||||
"sk": skid,
|
"sk": skid,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
authcoll.QuerySession = func(sk string, token string) common.AuthinfoCell {
|
authcoll.QuerySession = func(sk string, token string) gocommon.AuthinfoCell {
|
||||||
skid, _ := primitive.ObjectIDFromHex(sk)
|
skid, _ := primitive.ObjectIDFromHex(sk)
|
||||||
var outcell mongoAuthCell
|
var outcell mongoAuthCell
|
||||||
err := mongoClient.FindOneAs(CollectionAuth, bson.M{
|
err := mongoClient.FindOneAs(CollectionAuth, bson.M{
|
||||||
@ -119,7 +123,10 @@ func makeAuthCollection(mongoClient common.MongoClient, sessionTTL time.Duration
|
|||||||
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"`
|
||||||
|
MaximumNumLinkAccount int64 `json:"maximum_num_link_account"`
|
||||||
RedirectBaseUrl string `json:"redirect_base_url"`
|
RedirectBaseUrl string `json:"redirect_base_url"`
|
||||||
GoogleClientId string `json:"google_client_id"`
|
GoogleClientId string `json:"google_client_id"`
|
||||||
GoogleClientSecret string `json:"google_client_secret"`
|
GoogleClientSecret string `json:"google_client_secret"`
|
||||||
@ -137,6 +144,20 @@ type maingateConfig struct {
|
|||||||
GamepotProjectId string `json:"gamepot_project_id"`
|
GamepotProjectId string `json:"gamepot_project_id"`
|
||||||
GamepotLoginCheckAPIURL string `json:"gamepot_logincheckapi_url"`
|
GamepotLoginCheckAPIURL string `json:"gamepot_logincheckapi_url"`
|
||||||
FirebaseAdminSDKCredentialFile string `json:"firebase_admin_sdk_credentialfile"`
|
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 {
|
type globalAdmins struct {
|
||||||
@ -151,20 +172,21 @@ func (ga *globalAdmins) parse() {
|
|||||||
parsed[admin] = true
|
parsed[admin] = true
|
||||||
}
|
}
|
||||||
ga.emails = parsed
|
ga.emails = parsed
|
||||||
ga.modtime = common.ConfigModTime()
|
ga.modtime = gocommon.ConfigModTime()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Maingate :
|
// Maingate :
|
||||||
type Maingate struct {
|
type Maingate struct {
|
||||||
maingateConfig
|
maingateConfig
|
||||||
|
|
||||||
mongoClient common.MongoClient
|
mongoClient gocommon.MongoClient
|
||||||
|
|
||||||
auths *common.AuthCollection
|
auths *gocommon.AuthCollection
|
||||||
//services servicelist
|
//services servicelist
|
||||||
serviceptr unsafe.Pointer
|
serviceptr unsafe.Pointer
|
||||||
admins unsafe.Pointer
|
admins unsafe.Pointer
|
||||||
wl whitelist
|
wl memberContainerPtr[string, *whitelistmember]
|
||||||
|
bl memberContainerPtr[primitive.ObjectID, *blockinfo]
|
||||||
|
|
||||||
tokenEndpoints map[string]string
|
tokenEndpoints map[string]string
|
||||||
authorizationEndpoints map[string]string
|
authorizationEndpoints map[string]string
|
||||||
@ -174,31 +196,15 @@ type Maingate struct {
|
|||||||
firebaseAppContext context.Context
|
firebaseAppContext context.Context
|
||||||
}
|
}
|
||||||
|
|
||||||
var collectionNameMod = int32(0)
|
|
||||||
|
|
||||||
// New :
|
// New :
|
||||||
func New(ctx context.Context) (*Maingate, error) {
|
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
|
var config maingateConfig
|
||||||
if err := common.LoadConfig(&config); err != nil {
|
if err := gocommon.LoadConfig(&config); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var admins globalAdmins
|
var admins globalAdmins
|
||||||
if err := common.LoadConfig(&admins); err == nil {
|
if err := gocommon.LoadConfig(&admins); err == nil {
|
||||||
admins.parse()
|
admins.parse()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,7 +223,6 @@ func New(ctx context.Context) (*Maingate, error) {
|
|||||||
|
|
||||||
err := mg.prepare(ctx)
|
err := mg.prepare(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("mg.prepare() failed :", err)
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -297,100 +302,107 @@ func (mg *Maingate) discoverOpenIdConfiguration(name string, url string) error {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func makeErrorWithStack(err error) error {
|
||||||
|
return fmt.Errorf("%s\n%s", err.Error(), string(debug.Stack()))
|
||||||
|
}
|
||||||
|
|
||||||
func (mg *Maingate) prepare(context context.Context) (err error) {
|
func (mg *Maingate) prepare(context context.Context) (err error) {
|
||||||
if err := mg.discoverOpenIdConfiguration(AuthPlatformMicrosoft, "https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration"); err != nil {
|
if err := mg.discoverOpenIdConfiguration(AuthPlatformMicrosoft, "https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration"); err != nil {
|
||||||
return err
|
return makeErrorWithStack(err)
|
||||||
}
|
}
|
||||||
if err := mg.discoverOpenIdConfiguration("google", "https://accounts.google.com/.well-known/openid-configuration"); err != nil {
|
if err := mg.discoverOpenIdConfiguration("google", "https://accounts.google.com/.well-known/openid-configuration"); err != nil {
|
||||||
return err
|
return makeErrorWithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// redis에서 env를 가져온 후에
|
// redis에서 env를 가져온 후에
|
||||||
mg.mongoClient, err = common.NewMongoClient(context, mg.Mongo, "maingate")
|
mg.mongoClient, err = gocommon.NewMongoClient(context, mg.Mongo, "maingate")
|
||||||
if err != nil {
|
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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = mg.mongoClient.MakeUniqueIndices(CollectionAuth, map[string]bson.D{
|
if err = mg.mongoClient.MakeUniqueIndices(CollectionAuth, map[string]bson.D{
|
||||||
"skonly": {{Key: "sk", Value: 1}},
|
"skonly": {{Key: "sk", Value: 1}},
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return makeErrorWithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = mg.mongoClient.MakeUniqueIndices(CollectionLink, map[string]bson.D{
|
if err = mg.mongoClient.MakeUniqueIndices(CollectionLink, map[string]bson.D{
|
||||||
"platformuid": {{Key: "platform", Value: 1}, {Key: "uid", Value: 1}},
|
"platformuid": {{Key: "platform", Value: 1}, {Key: "uid", Value: 1}},
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return makeErrorWithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = mg.mongoClient.MakeUniqueIndices(CollectionLink, map[string]bson.D{
|
if err = mg.mongoClient.MakeUniqueIndices(CollectionLink, map[string]bson.D{
|
||||||
"emailplatform": {{Key: "email", Value: 1}, {Key: "platform", Value: 1}},
|
"emailplatform": {{Key: "email", Value: 1}, {Key: "platform", Value: 1}},
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return makeErrorWithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = mg.mongoClient.MakeIndices(CollectionWhitelist, map[string]bson.D{
|
if err = mg.mongoClient.MakeIndices(CollectionAccount, map[string]bson.D{
|
||||||
"service": {{Key: "service", Value: 1}},
|
"accid": {{Key: "accid", Value: 1}},
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return makeErrorWithStack(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{
|
if err = mg.mongoClient.MakeUniqueIndices(CollectionFile, map[string]bson.D{
|
||||||
"sk": {{Key: "service", Value: 1}, {Key: "key", Value: 1}},
|
"keyonly": {{Key: "key", Value: 1}},
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return makeErrorWithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err = mg.mongoClient.MakeExpireIndex(CollectionAccount, int32(mg.AccDelTTL)); err != nil {
|
||||||
|
return makeErrorWithStack(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = mg.mongoClient.MakeExpireIndex(CollectionLink, int32(mg.AccDelTTL)); err != nil {
|
||||||
|
return makeErrorWithStack(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete대신 _ts로 expire시킴. pipeline에 삭제 알려주기 위함
|
||||||
if err = mg.mongoClient.MakeExpireIndex(CollectionWhitelist, 10); err != nil {
|
if err = mg.mongoClient.MakeExpireIndex(CollectionWhitelist, 10); err != nil {
|
||||||
return err
|
return makeErrorWithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = mg.mongoClient.MakeExpireIndex(CollectionAuth, int32(mg.SessionTTL+300)); err != nil {
|
if err = mg.mongoClient.MakeExpireIndex(CollectionAuth, int32(mg.SessionTTL+300)); err != nil {
|
||||||
return err
|
return makeErrorWithStack(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 {
|
if err = mg.mongoClient.MakeExpireIndex(CollectionBlock, int32(3)); err != nil {
|
||||||
return err
|
return makeErrorWithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = mg.mongoClient.MakeUniqueIndices(CollectionPlatformLoginToken, map[string]bson.D{
|
if err = mg.mongoClient.MakeUniqueIndices(CollectionPlatformLoginToken, map[string]bson.D{
|
||||||
"platformauthtoken": {{Key: "platform", Value: 1}, {Key: "key", Value: 1}},
|
"platformauthtoken": {{Key: "platform", Value: 1}, {Key: "key", Value: 1}},
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return makeErrorWithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = mg.mongoClient.MakeExpireIndex(CollectionPlatformLoginToken, int32(mg.SessionTTL+300)); err != nil {
|
if err = mg.mongoClient.MakeExpireIndex(CollectionPlatformLoginToken, int32(mg.SessionTTL+300)); err != nil {
|
||||||
return err
|
return makeErrorWithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = mg.mongoClient.MakeUniqueIndices(CollectionUserToken, map[string]bson.D{
|
if err = mg.mongoClient.MakeUniqueIndices(CollectionUserToken, map[string]bson.D{
|
||||||
"platformusertoken": {{Key: "platform", Value: 1}, {Key: "userid", Value: 1}},
|
"platformusertoken": {{Key: "platform", Value: 1}, {Key: "userid", Value: 1}},
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return makeErrorWithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = mg.mongoClient.MakeUniqueIndices(CollectionGamepotUserInfo, map[string]bson.D{
|
if err = mg.mongoClient.MakeUniqueIndices(CollectionGamepotUserInfo, map[string]bson.D{
|
||||||
"gamepotuserid": {{Key: "gamepotuserid", Value: 1}},
|
"gamepotuserid": {{Key: "gamepotuserid", Value: 1}},
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return makeErrorWithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = mg.mongoClient.MakeUniqueIndices(CollectionFirebaseUserInfo, map[string]bson.D{
|
if err = mg.mongoClient.MakeUniqueIndices(CollectionFirebaseUserInfo, map[string]bson.D{
|
||||||
"firebaseuserid": {{Key: "firebaseuserid", Value: 1}},
|
"firebaseuserid": {{Key: "firebaseuserid", Value: 1}},
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return makeErrorWithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
mg.auths = makeAuthCollection(mg.mongoClient, time.Duration(mg.SessionTTL*int64(time.Second)))
|
mg.auths = makeAuthCollection(mg.mongoClient, time.Duration(mg.SessionTTL*int64(time.Second)))
|
||||||
@ -402,7 +414,7 @@ func (mg *Maingate) prepare(context context.Context) (err error) {
|
|||||||
if err = mg.mongoClient.FindAllAs(CollectionFile, nil, &preall, options.Find().SetProjection(bson.M{
|
if err = mg.mongoClient.FindAllAs(CollectionFile, nil, &preall, options.Find().SetProjection(bson.M{
|
||||||
"link": 1,
|
"link": 1,
|
||||||
})); err != nil {
|
})); err != nil {
|
||||||
return err
|
return makeErrorWithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, pre := range preall {
|
for _, pre := range preall {
|
||||||
@ -412,62 +424,41 @@ func (mg *Maingate) prepare(context context.Context) (err error) {
|
|||||||
}
|
}
|
||||||
logger.Println("saving files :", pre.Link)
|
logger.Println("saving files :", pre.Link)
|
||||||
|
|
||||||
var fulldoc fileDocumentDesc
|
var fulldoc FileDocumentDesc
|
||||||
err = mg.mongoClient.FindOneAs(CollectionFile, bson.M{
|
err = mg.mongoClient.FindOneAs(CollectionFile, bson.M{
|
||||||
"_id": pre.Id,
|
"_id": pre.Id,
|
||||||
}, &fulldoc)
|
}, &fulldoc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return makeErrorWithStack(err)
|
||||||
}
|
}
|
||||||
err = fulldoc.save()
|
err = fulldoc.Save()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return makeErrorWithStack(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var whites []whitelistmember
|
var whites []*whitelistmember
|
||||||
if err := mg.mongoClient.AllAs(CollectionWhitelist, &whites, options.Find().SetReturnKey(false)); err != nil {
|
if err := mg.mongoClient.AllAs(CollectionWhitelist, &whites, options.Find().SetReturnKey(false)); err != nil {
|
||||||
return err
|
return makeErrorWithStack(err)
|
||||||
}
|
}
|
||||||
mg.wl.init(whites)
|
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 watchAuthCollection(context, mg.auths, mg.mongoClient)
|
||||||
go mg.watchWhitelistCollection(context)
|
go mg.wl.watchCollection(context, CollectionWhitelist, mg.mongoClient)
|
||||||
|
go mg.bl.watchCollection(context, CollectionBlock, mg.mongoClient)
|
||||||
|
|
||||||
return nil
|
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 {
|
func (mg *Maingate) RegisterHandlers(ctx context.Context, serveMux *http.ServeMux, prefix string) error {
|
||||||
var allServices []*serviceDescription
|
var allServices []*serviceDescription
|
||||||
|
if err := mg.mongoClient.AllAs(CollectionService, &allServices, options.Find().SetReturnKey(false)); err != nil {
|
||||||
if *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/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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -482,14 +473,54 @@ func (mg *Maingate) RegisterHandlers(ctx context.Context, serveMux *http.ServeMu
|
|||||||
Id: primitive.NewObjectID(),
|
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)
|
empty.prepare(mg)
|
||||||
atomic.StorePointer(&mg.serviceptr, unsafe.Pointer(&empty))
|
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)
|
logger.Println("Service is registered :", mg.service().ServiceCode)
|
||||||
serveMux.Handle(common.MakeHttpHandlerPattern(prefix, mg.service().ServiceCode, "/"), mg.service())
|
serveMux.HandleFunc(gocommon.MakeHttpHandlerPattern(prefix, mg.service().ServiceCode, "/"), func(w http.ResponseWriter, r *http.Request) {
|
||||||
serveMux.HandleFunc(common.MakeHttpHandlerPattern(prefix, "api/"), mg.api)
|
mg.service().serveHTTP(w, r)
|
||||||
serveMux.HandleFunc(common.MakeHttpHandlerPattern(prefix, "query/"), mg.query)
|
})
|
||||||
|
serveMux.HandleFunc(gocommon.MakeHttpHandlerPattern(prefix, "api/"), mg.api)
|
||||||
|
serveMux.HandleFunc(gocommon.MakeHttpHandlerPattern(prefix, "query/"), mg.query)
|
||||||
|
|
||||||
configraw, _ := json.Marshal(mg.maingateConfig)
|
configraw, _ := json.Marshal(mg.maingateConfig)
|
||||||
var convertedConfig map[string]any
|
var convertedConfig map[string]any
|
||||||
@ -497,7 +528,7 @@ func (mg *Maingate) RegisterHandlers(ctx context.Context, serveMux *http.ServeMu
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
serveMux.HandleFunc(common.MakeHttpHandlerPattern(prefix, "config"), func(w http.ResponseWriter, r *http.Request) {
|
serveMux.HandleFunc(gocommon.MakeHttpHandlerPattern(prefix, "config"), func(w http.ResponseWriter, r *http.Request) {
|
||||||
defer func() {
|
defer func() {
|
||||||
s := recover()
|
s := recover()
|
||||||
if s != nil {
|
if s != nil {
|
||||||
@ -505,7 +536,7 @@ func (mg *Maingate) RegisterHandlers(ctx context.Context, serveMux *http.ServeMu
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if !*noauth {
|
if !*devflag {
|
||||||
apitoken := r.Header.Get("MG-X-API-TOKEN")
|
apitoken := r.Header.Get("MG-X-API-TOKEN")
|
||||||
if len(apitoken) == 0 {
|
if len(apitoken) == 0 {
|
||||||
logger.Println("MG-X-API-TOKEN is missing")
|
logger.Println("MG-X-API-TOKEN is missing")
|
||||||
@ -517,6 +548,8 @@ func (mg *Maingate) RegisterHandlers(ctx context.Context, serveMux *http.ServeMu
|
|||||||
if mg.service().isValidToken(apitokenObj) {
|
if mg.service().isValidToken(apitokenObj) {
|
||||||
convertedConfig["divisions"] = mg.service().Divisions
|
convertedConfig["divisions"] = mg.service().Divisions
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
convertedConfig["divisions"] = mg.service().Divisions
|
||||||
}
|
}
|
||||||
|
|
||||||
enc := json.NewEncoder(w)
|
enc := json.NewEncoder(w)
|
||||||
@ -528,30 +561,44 @@ func (mg *Maingate) RegisterHandlers(ctx context.Context, serveMux *http.ServeMu
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
fsx := http.FileServer(http.Dir("./console"))
|
cfsx := http.FileServer(http.Dir("console"))
|
||||||
serveMux.Handle(common.MakeHttpHandlerPattern(prefix, "console/"), http.StripPrefix("/console/", fsx))
|
pattern := gocommon.MakeHttpHandlerPattern(prefix, "console", "/")
|
||||||
|
serveMux.Handle(pattern, http.StripPrefix(pattern, cfsx))
|
||||||
|
logger.Println("maingate console registered :", pattern)
|
||||||
|
|
||||||
ssx := http.FileServer(http.Dir("./static"))
|
staticfs := http.FileServer(http.Dir("static"))
|
||||||
serveMux.Handle(common.MakeHttpHandlerPattern(prefix, "static/"), http.StripPrefix("/static/", ssx))
|
pattern = gocommon.MakeHttpHandlerPattern(prefix, "static", "/")
|
||||||
|
serveMux.Handle(pattern, http.StripPrefix(pattern, staticfs))
|
||||||
|
logger.Println("maingate static registered :", pattern)
|
||||||
|
|
||||||
serveMux.HandleFunc(common.MakeHttpHandlerPattern(prefix, "request_login_url", AuthPlatformGoogle), mg.platform_google_get_login_url)
|
fbafs := http.FileServer(http.Dir("fba"))
|
||||||
serveMux.HandleFunc(common.MakeHttpHandlerPattern(prefix, "authorize", AuthPlatformGoogle), mg.platform_google_authorize)
|
pattern = gocommon.MakeHttpHandlerPattern(prefix, "fba", "/")
|
||||||
serveMux.HandleFunc(common.MakeHttpHandlerPattern(prefix, "authorize_result", AuthPlatformGoogle), mg.platform_google_authorize_result)
|
serveMux.Handle(pattern, http.StripPrefix(pattern, fbafs))
|
||||||
|
logger.Println("google_analytics static registered :", pattern)
|
||||||
|
|
||||||
serveMux.HandleFunc(common.MakeHttpHandlerPattern(prefix, "request_login_url", AuthPlatformMicrosoft), mg.platform_microsoft_get_login_url)
|
serveMux.HandleFunc(gocommon.MakeHttpHandlerPattern(prefix, "fba", "fb-ga.min.js"), mg.google_analytics_js)
|
||||||
serveMux.HandleFunc(common.MakeHttpHandlerPattern(prefix, "authorize", AuthPlatformMicrosoft), mg.platform_microsoft_authorize)
|
logger.Println("google_analytics.js static registered :", pattern)
|
||||||
serveMux.HandleFunc(common.MakeHttpHandlerPattern(prefix, "authorize_result", AuthPlatformMicrosoft), mg.platform_microsoft_authorize_result)
|
|
||||||
|
|
||||||
serveMux.HandleFunc(common.MakeHttpHandlerPattern(prefix, "request_login_url", AuthPlatformTwitter), mg.platform_twitter_get_login_url)
|
serveMux.HandleFunc(gocommon.MakeHttpHandlerPattern(prefix, "request_login_url", AuthPlatformGoogle), mg.platform_google_get_login_url)
|
||||||
serveMux.HandleFunc(common.MakeHttpHandlerPattern(prefix, "authorize", AuthPlatformTwitter), mg.platform_twitter_authorize)
|
serveMux.HandleFunc(gocommon.MakeHttpHandlerPattern(prefix, "authorize", AuthPlatformGoogle), mg.platform_google_authorize)
|
||||||
serveMux.HandleFunc(common.MakeHttpHandlerPattern(prefix, "authorize_result", AuthPlatformTwitter), mg.platform_twitter_authorize_result)
|
serveMux.HandleFunc(gocommon.MakeHttpHandlerPattern(prefix, "authorize_result", AuthPlatformGoogle), mg.platform_google_authorize_result)
|
||||||
|
|
||||||
serveMux.HandleFunc(common.MakeHttpHandlerPattern(prefix, "request_login_url", AuthPlatformApple), mg.platform_apple_get_login_url)
|
serveMux.HandleFunc(gocommon.MakeHttpHandlerPattern(prefix, "request_login_url", AuthPlatformMicrosoft), mg.platform_microsoft_get_login_url)
|
||||||
serveMux.HandleFunc(common.MakeHttpHandlerPattern(prefix, "authorize", AuthPlatformApple), mg.platform_apple_authorize)
|
serveMux.HandleFunc(gocommon.MakeHttpHandlerPattern(prefix, "authorize", AuthPlatformMicrosoft), mg.platform_microsoft_authorize)
|
||||||
serveMux.HandleFunc(common.MakeHttpHandlerPattern(prefix, "authorize_result", AuthPlatformApple), mg.platform_apple_authorize_result)
|
serveMux.HandleFunc(gocommon.MakeHttpHandlerPattern(prefix, "authorize_result", AuthPlatformMicrosoft), mg.platform_microsoft_authorize_result)
|
||||||
|
|
||||||
serveMux.HandleFunc(common.MakeHttpHandlerPattern(prefix, "request_login_url", AuthPlatformFirebaseAuth), mg.platform_firebaseauth_get_login_url)
|
serveMux.HandleFunc(gocommon.MakeHttpHandlerPattern(prefix, "request_login_url", AuthPlatformTwitter), mg.platform_twitter_get_login_url)
|
||||||
serveMux.HandleFunc(common.MakeHttpHandlerPattern(prefix, "authorize_sdk", AuthPlatformFirebaseAuth), mg.platform_firebaseauth_authorize_sdk)
|
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)
|
||||||
|
|
||||||
go mg.watchServiceCollection(ctx, serveMux, prefix)
|
go mg.watchServiceCollection(ctx, serveMux, prefix)
|
||||||
go mg.watchFileCollection(ctx, serveMux, prefix)
|
go mg.watchFileCollection(ctx, serveMux, prefix)
|
||||||
@ -590,7 +637,7 @@ func (mg *Maingate) query(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !*noauth {
|
if !*devflag {
|
||||||
apitoken := r.Header.Get("MG-X-API-TOKEN")
|
apitoken := r.Header.Get("MG-X-API-TOKEN")
|
||||||
if len(apitoken) == 0 {
|
if len(apitoken) == 0 {
|
||||||
logger.Println("MG-X-API-TOKEN is missing")
|
logger.Println("MG-X-API-TOKEN is missing")
|
||||||
@ -722,6 +769,8 @@ func (mg *Maingate) updateUserinfo(info usertokeninfo) (bool, string, string) {
|
|||||||
success, userid, email = mg.platform_microsoft_getuserinfo(info)
|
success, userid, email = mg.platform_microsoft_getuserinfo(info)
|
||||||
case AuthPlatformGoogle:
|
case AuthPlatformGoogle:
|
||||||
success, userid, email = mg.platform_google_getuserinfo(info)
|
success, userid, email = mg.platform_google_getuserinfo(info)
|
||||||
|
case AuthPlatformSteamSDK:
|
||||||
|
success, userid, email = mg.platform_steamsdk_getuserinfo(info)
|
||||||
case AuthPlatformFirebaseAuth:
|
case AuthPlatformFirebaseAuth:
|
||||||
success, userid, email = mg.platform_firebase_getuserinfo(info)
|
success, userid, email = mg.platform_firebase_getuserinfo(info)
|
||||||
}
|
}
|
||||||
@ -762,13 +811,18 @@ func (mg *Maingate) getProviderInfo(platform string, uid string) (string, string
|
|||||||
if provider == "" || providerid == "" {
|
if provider == "" || providerid == "" {
|
||||||
return "", "", errors.New("getProviderInfo - firebase info not found: " + provider + " / " + providerid)
|
return "", "", errors.New("getProviderInfo - firebase info not found: " + provider + " / " + providerid)
|
||||||
}
|
}
|
||||||
|
case "":
|
||||||
|
//guest auth
|
||||||
|
providerid = uid
|
||||||
|
if providerid == "" {
|
||||||
|
return "", "", errors.New("getProviderInfo - guest provider id not found: " + provider + " / " + providerid)
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
provider = platform
|
provider = platform
|
||||||
providerid = uid
|
providerid = uid
|
||||||
}
|
if provider == "" || providerid == "" {
|
||||||
|
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
|
return provider, providerid, nil
|
||||||
@ -931,3 +985,31 @@ func JWTparseCode(keyurl string, code string) (string, string, string) {
|
|||||||
//--- nonce 체크 필요하다.
|
//--- nonce 체크 필요하다.
|
||||||
return claims["sub"].(string), email, 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
177
core/member_container.go
Normal file
177
core/member_container.go
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
126
core/platformsteam.go
Normal file
126
core/platformsteam.go
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
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
|
||||||
|
|
||||||
|
}
|
||||||
833
core/service.go
833
core/service.go
File diff suppressed because it is too large
Load Diff
144
core/watch.go
144
core/watch.go
@ -1,10 +1,8 @@
|
|||||||
package core
|
package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"context"
|
"context"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/json"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
@ -12,7 +10,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
common "repositories.action2quare.com/ayo/gocommon"
|
"repositories.action2quare.com/ayo/gocommon"
|
||||||
"repositories.action2quare.com/ayo/gocommon/logger"
|
"repositories.action2quare.com/ayo/gocommon/logger"
|
||||||
|
|
||||||
"go.mongodb.org/mongo-driver/bson"
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
@ -26,7 +24,7 @@ type authPipelineDocument struct {
|
|||||||
DocumentKey struct {
|
DocumentKey struct {
|
||||||
Id primitive.ObjectID `bson:"_id"`
|
Id primitive.ObjectID `bson:"_id"`
|
||||||
} `bson:"documentKey"`
|
} `bson:"documentKey"`
|
||||||
Authinfo *common.Authinfo `bson:"fullDocument"`
|
Authinfo *gocommon.Authinfo `bson:"fullDocument"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type servicePipelineDocument struct {
|
type servicePipelineDocument struct {
|
||||||
@ -42,103 +40,7 @@ type filePipelineDocument struct {
|
|||||||
DocumentKey struct {
|
DocumentKey struct {
|
||||||
Id primitive.ObjectID `bson:"_id"`
|
Id primitive.ObjectID `bson:"_id"`
|
||||||
} `bson:"documentKey"`
|
} `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) {
|
func (mg *Maingate) watchFileCollection(parentctx context.Context, serveMux *http.ServeMux, prefix string) {
|
||||||
@ -213,7 +115,7 @@ func (mg *Maingate) watchFileCollection(parentctx context.Context, serveMux *htt
|
|||||||
if err := stream.Decode(&data); err == nil {
|
if err := stream.Decode(&data); err == nil {
|
||||||
switch data.OperationType {
|
switch data.OperationType {
|
||||||
case "insert":
|
case "insert":
|
||||||
data.File.save()
|
data.File.Save()
|
||||||
|
|
||||||
case "delete":
|
case "delete":
|
||||||
subfolder := hex.EncodeToString(data.DocumentKey.Id[:4])
|
subfolder := hex.EncodeToString(data.DocumentKey.Id[:4])
|
||||||
@ -287,11 +189,9 @@ func (mg *Maingate) watchServiceCollection(parentctx context.Context, serveMux *
|
|||||||
logger.Error("service cannot be prepared :", data.Service, err)
|
logger.Error("service cannot be prepared :", data.Service, err)
|
||||||
} else {
|
} else {
|
||||||
// 내가 임시로 가지고 있던 서비스일 수 있다.
|
// 내가 임시로 가지고 있던 서비스일 수 있다.
|
||||||
already := mg.service().Id == data.Service.Id
|
if mg.service().Id == data.Service.Id {
|
||||||
logger.Println("service is on the board! :", data.Service)
|
logger.Println("service is on the board! :", data.Service)
|
||||||
atomic.StorePointer(&mg.serviceptr, unsafe.Pointer(data.Service))
|
atomic.StorePointer(&mg.serviceptr, unsafe.Pointer(data.Service))
|
||||||
if !already {
|
|
||||||
serveMux.Handle(common.MakeHttpHandlerPattern(prefix, data.Service.ServiceCode, "/"), mg.service())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -300,33 +200,7 @@ func (mg *Maingate) watchServiceCollection(parentctx context.Context, serveMux *
|
|||||||
|
|
||||||
case "update":
|
case "update":
|
||||||
data.Service.prepare(mg)
|
data.Service.prepare(mg)
|
||||||
old := mg.service()
|
atomic.StorePointer(&mg.serviceptr, unsafe.Pointer(data.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 {
|
} else {
|
||||||
logger.Error("watchServiceCollection stream.Decode failed :", err)
|
logger.Error("watchServiceCollection stream.Decode failed :", err)
|
||||||
@ -349,7 +223,7 @@ func (mg *Maingate) watchServiceCollection(parentctx context.Context, serveMux *
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func watchAuthCollection(parentctx context.Context, ac *common.AuthCollection, mongoClient common.MongoClient) {
|
func watchAuthCollection(parentctx context.Context, ac *gocommon.AuthCollection, mongoClient gocommon.MongoClient) {
|
||||||
defer func() {
|
defer func() {
|
||||||
s := recover()
|
s := recover()
|
||||||
if s != nil {
|
if s != nil {
|
||||||
|
|||||||
11
fba/track-event.html
Normal file
11
fba/track-event.html
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<!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
4
go.mod
@ -1,13 +1,13 @@
|
|||||||
module repositories.action2quare.com/ayo/maingate
|
module repositories.action2quare.com/ayo/maingate
|
||||||
|
|
||||||
go 1.19
|
go 1.18
|
||||||
|
|
||||||
require (
|
require (
|
||||||
firebase.google.com/go v3.13.0+incompatible
|
firebase.google.com/go v3.13.0+incompatible
|
||||||
github.com/golang-jwt/jwt v3.2.2+incompatible
|
github.com/golang-jwt/jwt v3.2.2+incompatible
|
||||||
go.mongodb.org/mongo-driver v1.11.7
|
go.mongodb.org/mongo-driver v1.11.7
|
||||||
google.golang.org/api v0.128.0
|
google.golang.org/api v0.128.0
|
||||||
repositories.action2quare.com/ayo/gocommon v0.0.0-20230621052811-06ef97f11d22
|
repositories.action2quare.com/ayo/gocommon v0.0.0-20240205060841-c31f838ba8a9
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
|||||||
55
go.sum
55
go.sum
@ -2,24 +2,16 @@ 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.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 h1:sdFPBr6xG9/wkBbfhmUz/JmZC7X6LavQgcrVINrKiVA=
|
||||||
cloud.google.com/go v0.110.2/go.mod h1:k04UEeEtb6ZBRTv3dZz4CeJC3jKGxyhl0sAiVVquxiw=
|
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 h1:6aKEtlUiwEpJzM001l0yFkpXmUVXaN8W+fbkb2AZNbg=
|
||||||
cloud.google.com/go/compute v1.20.1/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM=
|
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 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
|
||||||
cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
|
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 h1:FG5C49ukKKqyljY+XNRZGae1HZaiVe7aoqi2BipnBuM=
|
||||||
cloud.google.com/go/firestore v1.10.0/go.mod h1:eAeoQCV8F35Mcy4k8ZrQbcSYZOayIwoiU7ZJ6xzH1+o=
|
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 h1:lW7fzj15aVIXYHREOqjRBV9PsH0Z6u8Y46a1YGvQP4Y=
|
||||||
cloud.google.com/go/iam v1.1.1/go.mod h1:A5avdyVL2tCppe4unb0951eI9jreack+RJ0/d+KUZOU=
|
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 h1:Fr7TXftcqTudoyRJa113hyaqlGdiBQkp0Gq7tErFDWI=
|
||||||
cloud.google.com/go/longrunning v0.5.1/go.mod h1:spvimkwdz6SPWKEt/XBij79E9fiTkHSQl/fRUUQJYJc=
|
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 h1:uOdMxAs8HExqBlnLtnQyP0YkvbiDpdGShGKtx6U/oNM=
|
||||||
cloud.google.com/go/storage v1.30.1/go.mod h1:NfxhC0UJE1aXSx7CIIbCf7y9HKT7BiccwkR7+P7gN8E=
|
cloud.google.com/go/storage v1.30.1/go.mod h1:NfxhC0UJE1aXSx7CIIbCf7y9HKT7BiccwkR7+P7gN8E=
|
||||||
firebase.google.com/go v3.13.0+incompatible h1:3TdYC3DDi6aHn20qoRkxwGqNgdjtblwVAyRLQwGn/+4=
|
firebase.google.com/go v3.13.0+incompatible h1:3TdYC3DDi6aHn20qoRkxwGqNgdjtblwVAyRLQwGn/+4=
|
||||||
@ -94,16 +86,11 @@ 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.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 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
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 h1:UR4rDjcgpgEnqpIEvkiqTYKBCKLNmlge2eVjoZfySzM=
|
||||||
github.com/googleapis/enterprise-certificate-proxy v0.2.5/go.mod h1:RxW0N9901Cko1VOCW3SXCpWP+mlIEkk2tP7jnHy9a3w=
|
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 h1:9V9PWXEsWnPpQhu/PeQIkS4eGzMlTLGgt80cUUI8Ki4=
|
||||||
github.com/googleapis/gax-go/v2 v2.11.0/go.mod h1:DxmR61SGKkGLa2xigwuZIQpkCI2S5iydzRfb3peWZJI=
|
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/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.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||||
github.com/klauspost/compress v1.16.6 h1:91SKEy4K37vkp255cJ8QesJhjyRO0hn9i9G0GoUwLsk=
|
github.com/klauspost/compress v1.16.6 h1:91SKEy4K37vkp255cJ8QesJhjyRO0hn9i9G0GoUwLsk=
|
||||||
github.com/klauspost/compress v1.16.6/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
github.com/klauspost/compress v1.16.6/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||||
@ -112,7 +99,6 @@ 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/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 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
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.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 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE=
|
||||||
github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
|
github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
|
||||||
@ -141,21 +127,16 @@ github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
|
|||||||
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
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 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
|
||||||
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
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.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g=
|
||||||
github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY=
|
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/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.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 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8=
|
||||||
github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
|
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-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 h1:fZHgsYlfvtyqToslyjUt3VOPF4J7aK/3MPcK7xp3PDk=
|
||||||
github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a/go.mod h1:ul22v+Nro/R083muKhosV54bj5niojjWZvU8xrevuH4=
|
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=
|
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 h1:LIwYxASDLGUg/8wOhgOOZhX8tQa/9tgZPgzZoVqJvcs=
|
||||||
go.mongodb.org/mongo-driver v1.11.7/go.mod h1:G9TgswdsWjX4tmDA5zfs2+6AEPpYJwqblyjsfuh8oXY=
|
go.mongodb.org/mongo-driver v1.11.7/go.mod h1:G9TgswdsWjX4tmDA5zfs2+6AEPpYJwqblyjsfuh8oXY=
|
||||||
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
|
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
|
||||||
@ -167,8 +148,6 @@ 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-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-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.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 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM=
|
||||||
golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
|
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=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
@ -189,14 +168,10 @@ 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-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-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.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 h1:Gi2tvZIJyBtO9SDr1q9h5hEQCp/4L2RQ+ar0qjx2oNU=
|
||||||
golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ=
|
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-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.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 h1:BPpt2kU7oMRq3kCHAA1tbSEshXRw1LpG2ztgDwrzuAs=
|
||||||
golang.org/x/oauth2 v0.9.0/go.mod h1:qYgFZaFiu6Wg24azG8bdV52QJXJGbZzIIsRCdVKzbLw=
|
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=
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
@ -205,8 +180,6 @@ 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-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-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.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 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
|
||||||
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
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=
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
@ -219,8 +192,6 @@ 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-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-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.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 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s=
|
||||||
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
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=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
@ -231,8 +202,6 @@ 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.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.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
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 h1:UpjohKhiEgNc0CSauXmwYftY1+LlaC75SJwh0SgCX58=
|
||||||
golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||||
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
|
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
|
||||||
@ -249,8 +218,6 @@ 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-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 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk=
|
||||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
|
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 h1:RjPESny5CnQRn9V6siglged+DZCgfu9l6mO9dkX9VOg=
|
||||||
google.golang.org/api v0.128.0/go.mod h1:Y611qgqaE92On/7g65MQgxYul3c0rEB894kniWLY750=
|
google.golang.org/api v0.128.0/go.mod h1:Y611qgqaE92On/7g65MQgxYul3c0rEB894kniWLY750=
|
||||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||||
@ -261,8 +228,6 @@ 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-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-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-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 h1:8DyZCyvI8mE1IdLy/60bS+52xfymkE72wv1asokgtao=
|
||||||
google.golang.org/genproto v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:xZnkP7mREFX5MORlOPEzLMr+90PPZQ2QWzrVTWfAq64=
|
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=
|
google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc h1:kVKPf/IiYSBWEWtkIn6wZXwWGCnLKcC8oWfZvXjsGnM=
|
||||||
@ -277,8 +242,6 @@ 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.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||||
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
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.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 h1:+y7Bs8rtMd07LeXmL3NxcTLn7mUkbKZqEpPhMNkwJEE=
|
||||||
google.golang.org/grpc v1.56.0/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s=
|
google.golang.org/grpc v1.56.0/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s=
|
||||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||||
@ -305,17 +268,7 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
|||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
repositories.action2quare.com/ayo/gocommon v0.0.0-20230612013915-5950ff4bb82e h1:m0jo1r+2NtBfxwj92e6EVaBZpzTDT6Hq7D93vWO4h9Y=
|
repositories.action2quare.com/ayo/gocommon v0.0.0-20230912075917-f9a146321cdb h1:Rdf6uhBIWunRLZ2LIT1hSovYXxZoOzx9mdSK5bjWpos=
|
||||||
repositories.action2quare.com/ayo/gocommon v0.0.0-20230612013915-5950ff4bb82e/go.mod h1:ng62uGMGXyQSeuxePG5gJAMtip4Rnspu5Tu7hgvaXns=
|
repositories.action2quare.com/ayo/gocommon v0.0.0-20230912075917-f9a146321cdb/go.mod h1:rn6NA28Mej+qgLNx/Bu2wsdGyIycmacqlNP6gUXX2a0=
|
||||||
repositories.action2quare.com/ayo/gocommon v0.0.0-20230614091557-9b877d9a732c h1:fhCuu0jFps8T1sN8hO0fGnatvNDW6VwM96PV26EA3T4=
|
repositories.action2quare.com/ayo/gocommon v0.0.0-20240205060841-c31f838ba8a9 h1:5cQ60XjlI7k0qld0rIpd6gy7+a9csv3ijz1EVKTzsy8=
|
||||||
repositories.action2quare.com/ayo/gocommon v0.0.0-20230614091557-9b877d9a732c/go.mod h1:ng62uGMGXyQSeuxePG5gJAMtip4Rnspu5Tu7hgvaXns=
|
repositories.action2quare.com/ayo/gocommon v0.0.0-20240205060841-c31f838ba8a9/go.mod h1:rn6NA28Mej+qgLNx/Bu2wsdGyIycmacqlNP6gUXX2a0=
|
||||||
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=
|
|
||||||
|
|||||||
4
main.go
4
main.go
@ -6,7 +6,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
common "repositories.action2quare.com/ayo/gocommon"
|
"repositories.action2quare.com/ayo/gocommon"
|
||||||
"repositories.action2quare.com/ayo/gocommon/flagx"
|
"repositories.action2quare.com/ayo/gocommon/flagx"
|
||||||
"repositories.action2quare.com/ayo/gocommon/logger"
|
"repositories.action2quare.com/ayo/gocommon/logger"
|
||||||
"repositories.action2quare.com/ayo/maingate/core"
|
"repositories.action2quare.com/ayo/maingate/core"
|
||||||
@ -36,7 +36,7 @@ func main() {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
server := common.NewHTTPServer(serveMux)
|
server := gocommon.NewHTTPServer(serveMux)
|
||||||
logger.Println("maingate is started")
|
logger.Println("maingate is started")
|
||||||
if err := server.Start(); err != nil {
|
if err := server.Start(); err != nil {
|
||||||
logger.Error("maingate is stopped with error :", err)
|
logger.Error("maingate is stopped with error :", err)
|
||||||
|
|||||||
@ -4,27 +4,11 @@ $CurBranch = git branch --show-current
|
|||||||
|
|
||||||
Remove-Item maingate.zip -Force -Recurse -ErrorAction SilentlyContinue
|
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:GOOS="linux"
|
||||||
$Env:GOARCH="amd64"
|
$Env:GOARCH="amd64"
|
||||||
go build -ldflags="-s -w" .
|
go build -ldflags="-s -w" .
|
||||||
|
|
||||||
Compress-Archive -Path maingate -Update -DestinationPath maingate.zip
|
Compress-Archive -Path maingate -Update -DestinationPath maingate.zip
|
||||||
Compress-Archive -Path *-firebase-*.json -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
|
||||||
|
|||||||
1
template/fb-ga.min.js
vendored
Normal file
1
template/fb-ga.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user