diff --git a/core/api.go b/core/api.go index 8cd53f4..769f4cf 100644 --- a/core/api.go +++ b/core/api.go @@ -7,13 +7,11 @@ import ( "encoding/hex" "encoding/json" "errors" - "flag" "fmt" "io" "net/http" "os" "path" - "sort" "strconv" "strings" "sync/atomic" @@ -22,6 +20,7 @@ import ( common "repositories.action2quare.com/ayo/gocommon" "repositories.action2quare.com/ayo/gocommon/logger" + "repositories.action2quare.com/ayo/maingate/flag" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/primitive" @@ -76,79 +75,8 @@ func (fd *fileDocumentDesc) save() error { return err } -func (caller apiCaller) isGlobalAdmin() bool { - if *noauth { - return true - } - - email, ok := caller.userinfo["email"] - if !ok { - return false - } - - if _, ok := caller.globalAdmins[email.(string)]; ok { - return true - } - - return false -} - -func (caller apiCaller) writeAccessableServices(w http.ResponseWriter) { - services, editable := caller.getAccessableServices() - for _, r := range editable { - w.Header().Add("MG-X-SERVICE-EDITABLE", r) - } - - w.Write([]byte("{")) - start := true - for _, v := range services { - if !start { - w.Write([]byte(",")) - } - w.Write([]byte(fmt.Sprintf(`"%s":`, v.ServiceName))) - serptr := atomic.LoadPointer(&v.serviceSummarySerialized) - w.Write(*(*[]byte)(serptr)) - start = false - } - w.Write([]byte("}")) -} - -func (caller apiCaller) getAccessableServices() ([]*serviceDescription, []string) { - allservices := caller.mg.services.all() - - admin := caller.isGlobalAdmin() - var email string - if !*noauth { - v, ok := caller.userinfo["email"] - if !ok { - return nil, nil - } - - email = v.(string) - _, admin = caller.globalAdmins[email] - } - - var output []*serviceDescription - var editable []string - for _, desc := range allservices { - if admin { - output = append(output, desc) - editable = append(editable, desc.ServiceName) - } else if caller.isAdminOrValidToken(email) { - output = append(output, desc) - editable = append(editable, desc.ServiceName) - } - } - - sort.Slice(output, func(i, j int) bool { - return output[i].ServiceName < output[j].ServiceName - }) - - return output, editable -} - -func (caller apiCaller) isAdmin(service any) bool { - if *noauth { +func (caller apiCaller) isAdmin() bool { + if *flag.Noauth { return true } @@ -163,66 +91,49 @@ func (caller apiCaller) isAdmin(service any) bool { return true } - svcdesc := caller.mg.services.get(service) - if svcdesc == nil { - logger.Println("isVaidUser failed. service is missing :", service) - return false - } - - return svcdesc.isAdmin(email) + return caller.mg.service().isAdmin(email) } -func (caller apiCaller) isAdminOrValidToken(service any) bool { - if caller.isAdmin(service) { +func (caller apiCaller) isAdminOrValidToken() bool { + if caller.isAdmin() { return true } - sh := caller.mg.services.get(service) - if sh == nil { - return false - } - - return sh.isValidToken(caller.apiToken) + return caller.mg.service().isValidToken(caller.apiToken) } func (caller apiCaller) filesAPI(w http.ResponseWriter, r *http.Request) error { if r.Method == "GET" { - servicename := r.FormValue("service") - if !caller.isAdminOrValidToken(servicename) { + if !caller.isAdminOrValidToken() { w.WriteHeader(http.StatusUnauthorized) return nil } - var files []fileDocumentDesc - err := caller.mg.mongoClient.FindAllAs(CollectionFile, bson.M{ - "service": servicename, - }, &files, options.Find().SetProjection(bson.M{ + allfiles, err := caller.mg.mongoClient.All(CollectionFile, options.Find().SetProjection(bson.M{ "contents": 0, - })) + }).SetReturnKey(false)) if err != nil { return err } - if len(files) > 0 { + if len(allfiles) > 0 { enc := json.NewEncoder(w) - return enc.Encode(files) + return enc.Encode(allfiles) } } else if r.Method == "DELETE" { - servicename := r.FormValue("service") key := r.FormValue("key") - if len(servicename) == 0 || len(key) == 0 { + if len(key) == 0 { w.WriteHeader(http.StatusBadRequest) return nil } - if !caller.isAdminOrValidToken(servicename) { + if !caller.isAdminOrValidToken() { w.WriteHeader(http.StatusUnauthorized) return nil } _, err := caller.mg.mongoClient.Delete(CollectionFile, bson.M{ - "service": servicename, - "key": key, + "key": key, }) if err != nil { @@ -302,7 +213,7 @@ func (caller apiCaller) whitelistAPI(w http.ResponseWriter, r *http.Request) err if r.Method == "GET" { service := queryvals.Get("service") if len(service) > 0 { - if !caller.isAdminOrValidToken(service) { + if !caller.isAdminOrValidToken() { logger.Println("whitelistAPI failed. not vaild user :", r.Method, caller.userinfo) w.WriteHeader(http.StatusUnauthorized) return nil @@ -335,7 +246,7 @@ func (caller apiCaller) whitelistAPI(w http.ResponseWriter, r *http.Request) err return err } - if !caller.isAdminOrValidToken(member.Service) { + if !caller.isAdminOrValidToken() { logger.Println("whitelistAPI failed. not vaild user :", r.Method, caller.userinfo) w.WriteHeader(http.StatusUnauthorized) return nil @@ -378,22 +289,21 @@ func (caller apiCaller) whitelistAPI(w http.ResponseWriter, r *http.Request) err func (caller apiCaller) serviceAPI(w http.ResponseWriter, r *http.Request) error { mg := caller.mg - queryvals := r.URL.Query() if r.Method == "GET" { - name := queryvals.Get("name") - if len(name) > 0 { - if !caller.isAdminOrValidToken(name) { - logger.Println("serviceAPI failed. not vaild user :", r.Method, caller.userinfo) - w.WriteHeader(http.StatusBadRequest) - return nil + if mg.service().Id.IsZero() { + newService := serviceDescription{ + ServiceDescriptionSummary: ServiceDescriptionSummary{ + Id: primitive.NewObjectID(), + }, } - - w.Header().Add("MG-X-SERVICE-EDITABLE", name) - serptr := atomic.LoadPointer(&mg.services.get(name).serviceSerialized) - w.Write(*(*[]byte)(serptr)) - } else { - caller.writeAccessableServices(w) + if err := newService.prepare(caller.mg); err != nil { + return err + } + atomic.StorePointer(&mg.serviceptr, unsafe.Pointer(&newService)) } + + serptr := atomic.LoadPointer(&mg.service().serviceSerialized) + w.Write(*(*[]byte)(serptr)) } else if r.Method == "POST" { body, _ := io.ReadAll(r.Body) var service serviceDescription @@ -401,31 +311,7 @@ func (caller apiCaller) serviceAPI(w http.ResponseWriter, r *http.Request) error return err } - if service.Id.IsZero() { - if caller.isGlobalAdmin() { - service.Id = primitive.NewObjectID() - } else { - logger.Println("serviceAPI failed. not vaild user :", r.Method, caller.userinfo) - w.WriteHeader(http.StatusBadRequest) - return nil - } - } else if !caller.isAdminOrValidToken(service.Id) { - logger.Println("serviceAPI failed. not vaild user :", r.Method, caller.userinfo) - w.WriteHeader(http.StatusBadRequest) - return nil - } - - if len(service.ServerApiTokens) == 0 { - service.ServerApiTokens = []primitive.ObjectID{ - primitive.NewObjectID(), - } - } - filter := bson.M{"_id": service.Id} - if len(service.ServiceCode) == 0 { - service.ServiceCode = hex.EncodeToString(service.Id[6:]) - } - success, _, err := mg.mongoClient.Update(CollectionService, filter, bson.M{ "$set": &service, }, options.Update().SetUpsert(true)) @@ -445,28 +331,10 @@ func (caller apiCaller) serviceAPI(w http.ResponseWriter, r *http.Request) error func (caller apiCaller) maintenanceAPI(w http.ResponseWriter, r *http.Request) error { mg := caller.mg - queryvals := r.URL.Query() if r.Method == "GET" { - name := queryvals.Get("name") - if len(name) > 0 { - if !caller.isAdminOrValidToken(name) { - w.WriteHeader(http.StatusUnauthorized) - return nil - } - w.Header().Add("MG-X-SERVICE-EDITABLE", name) - serptr := atomic.LoadPointer(&mg.services.get(name).divisionsSerialized) - w.Write(*(*[]byte)(serptr)) - } else { - caller.writeAccessableServices(w) - } + serptr := atomic.LoadPointer(&mg.service().divisionsSerialized) + w.Write(*(*[]byte)(serptr)) } else if r.Method == "POST" { - servicename := queryvals.Get("name") - if !caller.isAdminOrValidToken(servicename) { - logger.Println("maintenanceAPI failed. not vaild user :", r.Method, caller.userinfo) - w.WriteHeader(http.StatusBadRequest) - return nil - } - var divs map[string]*Division dec := json.NewDecoder(r.Body) if err := dec.Decode(&divs); err != nil { @@ -475,7 +343,7 @@ func (caller apiCaller) maintenanceAPI(w http.ResponseWriter, r *http.Request) e } _, _, err := mg.mongoClient.Update(CollectionService, bson.M{ - "service": servicename, + "_Id": mg.service().Id, }, bson.M{ "$set": bson.M{"divisions": divs}, }, options.Update().SetUpsert(false)) @@ -498,7 +366,7 @@ func (caller apiCaller) accountAPI(w http.ResponseWriter, r *http.Request) error return nil } - if !caller.isAdminOrValidToken(service) { + if !caller.isAdminOrValidToken() { logger.Println("accountAPI failed. not vaild user :", r.Method, caller.userinfo) w.WriteHeader(http.StatusUnauthorized) return nil @@ -615,15 +483,14 @@ func (caller apiCaller) configAPI(w http.ResponseWriter, r *http.Request) error return errApiTokenMissing } - if _, exists := mg.apiTokenToService.get(apitoken); !exists { + apitokenObj, _ := primitive.ObjectIDFromHex(apitoken) + if !mg.service().isValidToken(apitokenObj) { return fmt.Errorf("mg-x-api-token is not valid : %s", apitoken) } return nil } -var noauth = flag.Bool("noauth", false, "") - type apiCaller struct { userinfo map[string]any globalAdmins map[string]bool @@ -646,7 +513,7 @@ func (mg *Maingate) api(w http.ResponseWriter, r *http.Request) { var userinfo map[string]any - if !*noauth { + if !*flag.Noauth { authheader := r.Header.Get("Authorization") if len(authheader) == 0 { logger.Println("Authorization header is not valid :", authheader) diff --git a/core/maingate.go b/core/maingate.go index 0e0e3c8..6c94c87 100644 --- a/core/maingate.go +++ b/core/maingate.go @@ -14,13 +14,13 @@ import ( "net/http" "os" "strings" - "sync" "sync/atomic" "time" "unsafe" common "repositories.action2quare.com/ayo/gocommon" "repositories.action2quare.com/ayo/gocommon/logger" + "repositories.action2quare.com/ayo/maingate/flag" "github.com/golang-jwt/jwt" "go.mongodb.org/mongo-driver/bson" @@ -61,7 +61,7 @@ const ( ) func SessionTTL() time.Duration { - if *common.Devflag { + if *flag.Devflag { return sessionTTLDev } @@ -73,7 +73,7 @@ type mongoAuthCell struct { } func init() { - if *common.Devflag { + if *flag.Devflag { hostname, _ := os.Hostname() CollectionLink = common.CollectionName(fmt.Sprintf("%s-%s", hostname, string(CollectionLink))) CollectionAuth = common.CollectionName(fmt.Sprintf("%s-%s", hostname, string(CollectionAuth))) @@ -129,33 +129,6 @@ func makeAuthCollection(mongoClient common.MongoClient, sessionTTL time.Duration return authcoll } -type apiTokenMap struct { - sync.Mutex - tokenToService map[string]string -} - -func (tm *apiTokenMap) add(token string, serviceCode string) { - tm.Lock() - defer tm.Unlock() - - tm.tokenToService[token] = serviceCode -} - -func (tm *apiTokenMap) remove(token string) { - tm.Lock() - defer tm.Unlock() - - delete(tm.tokenToService, token) -} - -func (tm *apiTokenMap) get(token string) (code string, exists bool) { - tm.Lock() - defer tm.Unlock() - - code, exists = tm.tokenToService[token] - return -} - type maingateConfig struct { Mongo string `json:"maingate_mongodb_url"` SessionTTL int64 `json:"maingate_session_ttl"` @@ -194,104 +167,16 @@ func (ga *globalAdmins) parse() { ga.modtime = common.ConfigModTime() } -type servicelist struct { - services unsafe.Pointer -} - -func (sl *servicelist) init(total []*serviceDescription) error { - next := make(map[string]*serviceDescription) - for _, service := range total { - next[service.ServiceName] = service - } - - atomic.StorePointer(&sl.services, unsafe.Pointer(&next)) - return nil -} - -func (sl *servicelist) add(s *serviceDescription) { - ptr := atomic.LoadPointer(&sl.services) - src := (*map[string]*serviceDescription)(ptr) - - next := map[string]*serviceDescription{} - for k, v := range *src { - next[k] = v - } - next[s.ServiceName] = s - atomic.StorePointer(&sl.services, unsafe.Pointer(&next)) -} - -func (sl *servicelist) getByCode(code string) *serviceDescription { - ptr := atomic.LoadPointer(&sl.services) - src := *(*map[string]*serviceDescription)(ptr) - - for _, v := range src { - if v.ServiceCode == code { - return v - } - } - return nil -} - -func (sl *servicelist) get(sn any) *serviceDescription { - ptr := atomic.LoadPointer(&sl.services) - src := *(*map[string]*serviceDescription)(ptr) - - switch sn := sn.(type) { - case string: - return src[sn] - - case primitive.ObjectID: - for _, desc := range src { - if desc.Id == sn { - return desc - } - } - } - - return nil -} - -func (sl *servicelist) all() map[string]*serviceDescription { - ptr := atomic.LoadPointer(&sl.services) - src := (*map[string]*serviceDescription)(ptr) - - next := map[string]*serviceDescription{} - for k, v := range *src { - next[k] = v - } - - return next -} - -func (sl *servicelist) remove(uid primitive.ObjectID) (out *serviceDescription) { - ptr := atomic.LoadPointer(&sl.services) - src := (*map[string]*serviceDescription)(ptr) - - next := map[string]*serviceDescription{} - var targetkey string - out = nil - for k, v := range *src { - next[k] = v - if v.Id == uid { - targetkey = k - out = v - } - } - delete(next, targetkey) - atomic.StorePointer(&sl.services, unsafe.Pointer(&next)) - return -} - // Maingate : type Maingate struct { maingateConfig mongoClient common.MongoClient - auths *common.AuthCollection - services servicelist + auths *common.AuthCollection + //services servicelist + serviceptr unsafe.Pointer admins unsafe.Pointer - apiTokenToService apiTokenMap tokenEndpoints map[string]string authorizationEndpoints map[string]string userinfoEndpoint map[string]string @@ -318,12 +203,8 @@ func New(ctx context.Context) (*Maingate, error) { } mg := Maingate{ - maingateConfig: config, - services: servicelist{}, - admins: unsafe.Pointer(&admins), - apiTokenToService: apiTokenMap{ - tokenToService: make(map[string]string), - }, + maingateConfig: config, + admins: unsafe.Pointer(&admins), tokenEndpoints: make(map[string]string), authorizationEndpoints: make(map[string]string), userinfoEndpoint: make(map[string]string), @@ -352,6 +233,11 @@ func New(ctx context.Context) (*Maingate, error) { return &mg, nil } +func (mg *Maingate) service() *serviceDescription { + valptr := atomic.LoadPointer(&mg.serviceptr) + return (*serviceDescription)(valptr) +} + func (mg *Maingate) Destructor() { logger.Println("maingate.Destructor") mg.mongoClient.Close() @@ -554,23 +440,19 @@ func whitelistKey(email string) string { func (mg *Maingate) RegisterHandlers(ctx context.Context, serveMux *http.ServeMux, prefix string) error { var allServices []*serviceDescription logger.Println(CollectionService) - if err := mg.mongoClient.FindAllAs(CollectionService, bson.M{}, &allServices, options.Find().SetReturnKey(false)); err != nil { + if err := mg.mongoClient.AllAs(CollectionService, &allServices, options.Find().SetReturnKey(false)); err != nil { return err } - for _, service := range allServices { - if err := service.prepare(mg); err != nil { - return err - } - } - - logger.Println("RegisterHandlers...") - mg.services.init(allServices) - for _, service := range allServices { - logger.Println("ServiceCode:", service.ServiceCode) - serveMux.Handle(common.MakeHttpHandlerPattern(prefix, service.ServiceCode, "/"), service) + if len(allServices) > 0 { + only := allServices[0] + only.prepare(mg) + + atomic.StorePointer(&mg.serviceptr, unsafe.Pointer(only)) } + logger.Println("Service is registered :", mg.service().ServiceCode) + serveMux.Handle(common.MakeHttpHandlerPattern(prefix, mg.service().ServiceCode, "/"), mg.service()) serveMux.HandleFunc(common.MakeHttpHandlerPattern(prefix, "api/"), mg.api) serveMux.HandleFunc(common.MakeHttpHandlerPattern(prefix, "query/"), mg.query) @@ -595,16 +477,10 @@ func (mg *Maingate) RegisterHandlers(ctx context.Context, serveMux *http.ServeMu return } - code, exists := mg.apiTokenToService.get(apitoken) - if !exists { - logger.Println("MG-X-API-TOKEN is invalid :", apitoken) - w.WriteHeader(http.StatusBadRequest) - return + apitokenObj, _ := primitive.ObjectIDFromHex(apitoken) + if mg.service().isValidToken(apitokenObj) { + convertedConfig["divisions"] = mg.service().Divisions } - - service := mg.services.getByCode(code) - convertedConfig["divisions"] = service.Divisions - enc := json.NewEncoder(w) enc.Encode(convertedConfig) }) @@ -687,19 +563,13 @@ func (mg *Maingate) query(w http.ResponseWriter, r *http.Request) { return } - servicecode, exists := mg.apiTokenToService.get(apitoken) - if !exists { + apitokenObj, _ := primitive.ObjectIDFromHex(apitoken) + if !mg.service().isValidToken(apitokenObj) { logger.Println("MG-X-API-TOKEN is invalid :", apitoken) w.WriteHeader(http.StatusBadRequest) return } - if info.ServiceCode != servicecode { - logger.Println("session is not for this service :", info.ServiceCode, servicecode) - w.WriteHeader(http.StatusBadRequest) - return - } - bt, _ := json.Marshal(info) w.Write(bt) } diff --git a/core/service.go b/core/service.go index f5598a1..9373f7f 100644 --- a/core/service.go +++ b/core/service.go @@ -31,7 +31,6 @@ type blockinfo struct { type whitelistMemberTag = string type whitelistmember struct { - Service string `bson:"service" json:"service"` Email string `bson:"email" json:"email"` Platform string `bson:"platform" json:"platform"` Desc string `bson:"desc" json:"desc"` @@ -130,7 +129,6 @@ type Division struct { type ServiceDescriptionSummary struct { Id primitive.ObjectID `bson:"_id" json:"_id"` - ServiceName string `bson:"service" json:"service"` ServiceCode string `bson:"code" json:"code"` } @@ -230,7 +228,7 @@ func (sh *serviceDescription) prepare(mg *Maingate) error { div.Maintenance.link = div.Maintenance.Notice } else { hasher := md5.New() - hasher.Write([]byte(sh.ServiceName)) + hasher.Write(sh.Id[:]) subfolder := hex.EncodeToString(hasher.Sum(nil))[:8] div.Maintenance.link = path.Join("static", subfolder, div.Maintenance.Notice) @@ -260,25 +258,19 @@ func (sh *serviceDescription) prepare(mg *Maingate) error { sh.getProviderInfo = mg.getProviderInfo var whites []whitelistmember - if err := mg.mongoClient.FindAllAs(CollectionWhitelist, bson.M{ - "$or": []bson.M{{"service": sh.ServiceName}, {"service": sh.ServiceCode}}, - }, &whites, options.Find().SetReturnKey(false)); err != nil { + if err := mg.mongoClient.AllAs(CollectionWhitelist, &whites, options.Find().SetReturnKey(false)); err != nil { return err } sh.wl.init(whites) sh.admins = unsafe.Pointer(&sh.Admins) - for _, keyid := range sh.ServerApiTokens { - mg.apiTokenToService.add(keyid.Hex(), sh.ServiceCode) - } - bt, _ := json.Marshal(sh) atomic.StorePointer(&sh.serviceSerialized, unsafe.Pointer(&bt)) btsum, _ := json.Marshal(sh.ServiceDescriptionSummary) atomic.StorePointer(&sh.serviceSummarySerialized, unsafe.Pointer(&btsum)) - logger.Println("service is ready :", sh.ServiceName, sh.ServiceCode, sh.Admins, string(divmarshaled)) + logger.Println("service is ready :", sh.ServiceCode, sh.Admins, string(divmarshaled)) return nil } @@ -380,7 +372,7 @@ func (sh *serviceDescription) link(w http.ResponseWriter, r *http.Request) { return } - _, newid, err := sh.mongoClient.Update(common.CollectionName(sh.ServiceName), bson.M{ + _, newid, err := sh.mongoClient.Update(CollectionService, bson.M{ "_id": link["_id"].(primitive.ObjectID), }, bson.M{ "$setOnInsert": bson.M{ @@ -489,7 +481,7 @@ func (sh *serviceDescription) authorize(w http.ResponseWriter, r *http.Request) for i := 0; i < len(sh.serviceCodeBytes); i++ { newaccid[i] ^= sh.serviceCodeBytes[i] } - account, err := sh.mongoClient.FindOneAndUpdate(common.CollectionName(sh.ServiceName), bson.M{ + account, err := sh.mongoClient.FindOneAndUpdate(CollectionService, bson.M{ "_id": linkid, }, bson.M{ "$setOnInsert": bson.M{ diff --git a/core/watch.go b/core/watch.go index d8cd4f2..1e85173 100644 --- a/core/watch.go +++ b/core/watch.go @@ -10,6 +10,7 @@ import ( "path" "sync/atomic" "time" + "unsafe" common "repositories.action2quare.com/ayo/gocommon" "repositories.action2quare.com/ayo/gocommon/logger" @@ -109,18 +110,14 @@ func (mg *Maingate) watchWhitelistCollection(parentctx context.Context) { switch ot { case "insert": // 새 화이트리스트 멤버 - if svc := mg.services.get(data.Member.Service); svc != nil { - svc.wl.add(data.Member) - } + mg.service().wl.add(data.Member) case "update": - if svc := mg.services.get(data.Member.Service); svc != nil { - if data.Member.Expired != 0 { - logger.Println("whitelist member is removed :", *data.Member) - svc.wl.remove(data.Member.Email) - } else { - logger.Println("whitelist member is updated :", *data.Member) - svc.wl.add(data.Member) - } + 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 { @@ -242,7 +239,6 @@ func (mg *Maingate) watchServiceCollection(parentctx context.Context, serveMux * Key: "$match", Value: bson.D{ {Key: "operationType", Value: bson.D{ {Key: "$in", Value: bson.A{ - "delete", "insert", "update", "replace", @@ -291,8 +287,8 @@ func (mg *Maingate) watchServiceCollection(parentctx context.Context, serveMux * logger.Error("service cannot be prepared :", data.Service, err) } else { logger.Println("service is on the board! :", data.Service) - mg.services.add(data.Service) - serveMux.Handle(common.MakeHttpHandlerPattern(prefix, data.Service.ServiceCode, "/"), data.Service) + atomic.StorePointer(&mg.serviceptr, unsafe.Pointer(data.Service)) + serveMux.Handle(common.MakeHttpHandlerPattern(prefix, data.Service.ServiceCode, "/"), mg.service()) } case "replace": @@ -300,49 +296,32 @@ func (mg *Maingate) watchServiceCollection(parentctx context.Context, serveMux * case "update": data.Service.prepare(mg) - if old := mg.services.get(data.Service.ServiceName); old != nil { - 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) + old := mg.service() - for _, token := range old.ServerApiTokens { - mg.apiTokenToService.remove(token.Hex()) + 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)) } - for _, token := range data.Service.ServerApiTokens { - mg.apiTokenToService.add(token.Hex(), data.Service.ServiceCode) - } - - 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() - } + if req != nil { + // MG-X-API-TOKEN + req.Header.Add("MG-X-API-TOKEN", old.ServerApiTokens[0].Hex()) + if resp, err := http.DefaultClient.Do(req); err == nil { + resp.Body.Close() } } - } else { - logger.Println("service is on the board! :", data.Service) - mg.services.add(data.Service) - serveMux.Handle(common.MakeHttpHandlerPattern(prefix, data.Service.ServiceCode, "/"), data.Service) - } - case "delete": - if deleted := mg.services.remove(data.DocumentKey.Id); deleted != nil { - logger.Println("service is closed :", data.Service) } } } else { diff --git a/flag/commandline.go b/flag/commandline.go new file mode 100644 index 0000000..c8c92a8 --- /dev/null +++ b/flag/commandline.go @@ -0,0 +1,18 @@ +package flag + +import ( + "flag" + "os" +) + +var commandLine = flag.NewFlagSet("maingate", flag.ExitOnError) +var Devflag = commandLine.Bool("dev", false, "") +var Noauth = commandLine.Bool("noauth", false, "") + +func Parsed() bool { + return commandLine.Parsed() +} + +func Parse() error { + return commandLine.Parse(os.Args[1:]) +} diff --git a/go.mod b/go.mod index 43ac32d..5f0b90a 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/golang-jwt/jwt v3.2.2+incompatible go.mongodb.org/mongo-driver v1.11.6 google.golang.org/api v0.123.0 - repositories.action2quare.com/ayo/gocommon v0.0.0-20230616032216-378bc19f3742 + repositories.action2quare.com/ayo/gocommon v0.0.0-20230620005911-15ba3e93d621 ) require ( diff --git a/go.sum b/go.sum index f1522a6..ad96cbf 100644 --- a/go.sum +++ b/go.sum @@ -266,3 +266,5 @@ repositories.action2quare.com/ayo/gocommon v0.0.0-20230616031450-0b2c9351a717 h1 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= diff --git a/main.go b/main.go index de90c94..1916f87 100644 --- a/main.go +++ b/main.go @@ -2,13 +2,13 @@ package main import ( "context" - "flag" "math/rand" "net/http" "time" common "repositories.action2quare.com/ayo/gocommon" "repositories.action2quare.com/ayo/maingate/core" + flag "repositories.action2quare.com/ayo/maingate/flag" "repositories.action2quare.com/ayo/gocommon/logger" )