package core import ( "encoding/json" "io" "net/http" common "repositories.action2quare.com/ayo/gocommon" "repositories.action2quare.com/ayo/gocommon/logger" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/primitive" ) // CreateGroup : 그룹 생성 // - 그룹 : 멤버와 권한을 관리할 수 있다. 그룹 타입에 따라 디비에 저장되거나 메모리에만 존재한다. // - 생성 요청이 오면 파티를 만든다. 파티을 만들 수 있는지 여부는 서비스에서 결정할 것이고, 이 요청을 호출했다는 것은 서비스가 결정한 그룹 생성 조건을 다 통과했다는 의미이다. // - parameter : // - type : 그룹 종류. 그룹 종류에 따라 인덱스와 쿼리 가능 field가 다르다. func (sub *subTavern) CreateGroup(w http.ResponseWriter, r *http.Request) { typename, _ := common.ReadStringFormValue(r.Form, "type") grouptype := sub.groups[typename] if grouptype == nil { logger.Println("CreateGroup failed. group type is missing :", r.Form) w.WriteHeader(http.StatusBadRequest) return } doc := bson.M{} if err := readBsonDoc(r.Body, &doc); err != nil { logger.Error("CreateGroup failed. readBsonDoc returns err :", err) w.WriteHeader(http.StatusBadRequest) return } inserted, err := grouptype.Create(r.Form, doc) if err != nil { w.WriteHeader(http.StatusBadRequest) return } w.Write(inserted[:]) } // JoinGroup : 그룹에 참가 // - type : 그룹 타입 // - 그룹 타입에 맞는 키(주로 _id) // - member_id : 참가 멤버의 아이디 // - body : 멤버의 속성 bson document func (sub *subTavern) JoinGroup(w http.ResponseWriter, r *http.Request) { typename, _ := common.ReadStringFormValue(r.Form, "type") group := sub.groups[typename] if group == nil { logger.Println("JoinGroup failed. group type is missing :", r.Form) w.WriteHeader(http.StatusBadRequest) return } doc := bson.M{} if err := readBsonDoc(r.Body, &doc); err != nil { logger.Error("JoinGroup failed. readBsonDoc returns err :", err) w.WriteHeader(http.StatusBadRequest) return } gidobj, ok := common.ReadObjectIDFormValue(r.Form, "gid") if !ok { logger.Println("JoinGroup failed. gid is missing :", r.Form) w.WriteHeader(http.StatusBadRequest) return } midobj, midok := common.ReadObjectIDFormValue(r.Form, "mid") tidobj, tidok := common.ReadObjectIDFormValue(r.Form, "tid") if !midok && !tidok { // 둘다 없네? logger.Println("JoinGroup failed. tid or mid should be exist") w.WriteHeader(http.StatusBadRequest) return } var err error if candidate, ok := common.ReadBoolFormValue(r.Form, "candidate"); ok && candidate { err = group.Candidate(gidobj, midobj, doc) } else { err = group.Join(gidobj, midobj, doc) } if err == nil { json.NewEncoder(w).Encode(map[string]string{ "gid": gidobj.Hex(), "tid": tidobj.Hex(), }) } else if err == errGroupNotExist { w.Write([]byte("{}")) } else if err != nil { logger.Error("JoinGroup failed :", err) w.WriteHeader(http.StatusInternalServerError) } } // Invite : 초대 // - type : 초대 타입 (required) // - from : 초대하는 자 (required) // - to : 초대받는 자 (required) // - timeout : 초대 유지시간(optional. 없으면 config 기본 값) // - (body) : 검색시 노출되는 document func (sub *subTavern) Invite(w http.ResponseWriter, r *http.Request) { typename, _ := common.ReadStringFormValue(r.Form, "type") group := sub.groups[typename] if group == nil { logger.Println("Invite failed. group type is missing :", r) w.WriteHeader(http.StatusBadRequest) return } gid, ok := common.ReadObjectIDFormValue(r.Form, "gid") if !ok { logger.Println("Invite failed. gid is missing :", r) w.WriteHeader(http.StatusBadRequest) return } mid, ok := common.ReadObjectIDFormValue(r.Form, "mid") if !ok { logger.Println("Invite failed. mid is missing :", r) w.WriteHeader(http.StatusBadRequest) return } var reqdoc struct { Inviter bson.M `bson:"inviter"` Invitee bson.M `bson:"invitee"` } if err := readBsonDoc(r.Body, &reqdoc); err != nil { logger.Error("Invite failed. readBsonDoc returns err :", err) w.WriteHeader(http.StatusInternalServerError) return } result, err := group.Invite(gid, mid, reqdoc.Inviter, reqdoc.Invitee) if err != nil { logger.Error("Invite failed. group.Invite returns err :", err) w.WriteHeader(http.StatusInternalServerError) return } w.Write([]byte(result)) } func (sub *subTavern) CancelInvitation(w http.ResponseWriter, r *http.Request) { typename, _ := common.ReadStringFormValue(r.Form, "type") group := sub.groups[typename] if group == nil { logger.Println("CancelInvitation failed. group type is missing :", r) w.WriteHeader(http.StatusBadRequest) return } tid, ok := common.ReadObjectIDFormValue(r.Form, "tid") if !ok { logger.Println("CancelInvitation failed. form value 'tid' is missing") w.WriteHeader(http.StatusBadRequest) return } gid, ok := common.ReadObjectIDFormValue(r.Form, "gid") if !ok { logger.Println("CancelInvitation failed. form value 'gid' is missing") w.WriteHeader(http.StatusBadRequest) return } if err := group.CancelInvitation(gid, tid); err != nil { logger.Println("CancelInvitation failed. group.CancelInvitation returns err :", err) w.WriteHeader(http.StatusInternalServerError) } } func (sub *subTavern) AcceptInvitation(w http.ResponseWriter, r *http.Request) { typename, _ := common.ReadStringFormValue(r.Form, "type") group := sub.groups[typename] if group == nil { logger.Println("CancelInvitation failed. group type is missing :", r) w.WriteHeader(http.StatusBadRequest) return } gid, _ := common.ReadObjectIDFormValue(r.Form, "gid") mid, _ := common.ReadObjectIDFormValue(r.Form, "mid") var member bson.M if err := readBsonDoc(r.Body, &member); err != nil { logger.Error("AcceptInvitation failed. readBsonDoc returns err :", err) w.WriteHeader(http.StatusInternalServerError) return } err := group.AcceptInvitation(gid, mid, member) if err != nil { logger.Error("AcceptInvitation failed. group.AcceptInvitation returns err :", err) w.WriteHeader(http.StatusInternalServerError) return } // TODO : full group doc을 내려보냄 // w.Write([]byte(gidbytes.Hex())) } func (sub *subTavern) DenyInvitation(w http.ResponseWriter, r *http.Request) { typename, _ := common.ReadStringFormValue(r.Form, "type") group := sub.groups[typename] if group == nil { logger.Println("DenyInvitation failed. group type is missing") w.WriteHeader(http.StatusBadRequest) return } gid, _ := common.ReadObjectIDFormValue(r.Form, "gid") mid, _ := common.ReadObjectIDFormValue(r.Form, "mid") tid, ok := common.ReadObjectIDFormValue(r.Form, "tid") if !ok { logger.Println("DenyInvitation failed. tid is missing") w.WriteHeader(http.StatusBadRequest) return } err := group.DenyInvitation(gid, mid, tid) if err != nil { logger.Error("DenyInvitation failed. group.DenyInvitation returns err :", err) w.WriteHeader(http.StatusInternalServerError) return } } func (sub *subTavern) QueryInvitations(w http.ResponseWriter, r *http.Request) { typename, _ := common.ReadStringFormValue(r.Form, "type") group := sub.groups[typename] if group == nil { logger.Println("QueryInvitations failed. group type is missing :", r.Form) w.WriteHeader(http.StatusBadRequest) return } mid, ok := common.ReadObjectIDFormValue(r.Form, "mid") if !ok { logger.Println("QueryInvitations failed. mid is missing :", r.Form) w.WriteHeader(http.StatusBadRequest) return } var after primitive.Timestamp if v, ok := common.ReadStringFormValue(r.Form, "after"); ok && v != "0.0" { after = common.DotStringToTimestamp(v) } result, err := group.QueryInvitations(mid, after) if err != nil { logger.Println("QueryInvitations failed. group.QueryInvitations returns err :", err) w.WriteHeader(http.StatusInternalServerError) return } if err := writeBsonArr(w, result); err != nil { logger.Println("QueryInvitations failed. Encode returns err :", err) w.WriteHeader(http.StatusInternalServerError) return } } func (sub *subTavern) SearchGroup(w http.ResponseWriter, r *http.Request) { typename, _ := common.ReadStringFormValue(r.Form, "type") group := sub.groups[typename] if group == nil { logger.Println("SearchGroup failed. group type is missing :", r.Form) w.WriteHeader(http.StatusBadRequest) return } projection, _ := common.ReadStringFormValue(r.Form, "projection") var filter bson.M if err := readBsonDoc(r.Body, &filter); err != nil { logger.Error("SearchGroup failed. readBsonDoc returns err :", err) w.WriteHeader(http.StatusBadRequest) return } result, err := group.FindAll(filter, projection, primitive.Timestamp{}) if err != nil { logger.Error("SearchGroup failed. FindAll err :", err) w.WriteHeader(http.StatusInternalServerError) return } if result == nil { return } if err := writeBsonArr(w, result); err != nil { logger.Error("json marshal failed :", err) w.WriteHeader(http.StatusInternalServerError) return } } func (sub *subTavern) QueryOnlineState(w http.ResponseWriter, r *http.Request) { mid, ok := common.ReadObjectIDFormValue(r.Form, "mid") if !ok { logger.Println("IsOnline failed. mid is missing :", r.Form) w.WriteHeader(http.StatusBadRequest) return } state := sub.wsh.GetState(sub.region, mid) w.Write([]byte(state)) } func (sub *subTavern) IsOnline(w http.ResponseWriter, r *http.Request) { mid, ok := common.ReadObjectIDFormValue(r.Form, "mid") if !ok { logger.Println("IsOnline failed. mid is missing :", r.Form) w.WriteHeader(http.StatusBadRequest) return } if state := sub.wsh.GetState(sub.region, mid); len(state) > 0 { w.Write([]byte("true")) } else { w.Write([]byte("false")) } } // QueryGroup : 그룹조회 // - type : 그룹 타입 // - 그룹 타입에 맞는 키(주로 _id) // - projection : select할 필드. ,로 구분 func (sub *subTavern) QueryGroup(w http.ResponseWriter, r *http.Request) { typename, _ := common.ReadStringFormValue(r.Form, "type") group := sub.groups[typename] if group == nil { logger.Println("QueryGroup failed. group type is missing :", r.Form) w.WriteHeader(http.StatusBadRequest) return } gid, ok := common.ReadObjectIDFormValue(r.Form, "_id") if !ok { logger.Println("QueryGroup failed. _id is missing :", r.Form) w.WriteHeader(http.StatusBadRequest) return } projection, _ := common.ReadStringFormValue(r.Form, "projection") after, _ := common.ReadStringFormValue(r.Form, "after") if after != "0.0" { projection += ",+luts" } result, err := group.FindOne(gid, projection) if err != nil { w.WriteHeader(http.StatusInternalServerError) return } if result == nil { return } if len(after) > 0 { if luts, ok := result["luts"].(primitive.Timestamp); ok { afterts := common.DotStringToTimestamp(after) if primitive.CompareTimestamp(luts, afterts) < 0 { return } } } if err := writeBsonDoc(w, result); err != nil { logger.Error("json marshal failed :", err) w.WriteHeader(http.StatusInternalServerError) return } } // LeaveGroup : 그룹에서 나감 or 내보냄 // - type : 그룹 타입 // - 그룹 타입에 맞는 키(주로 _id) // - member_id : 나갈 멤버의 아이디 func (sub *subTavern) LeaveGroup(w http.ResponseWriter, r *http.Request) { typename, _ := common.ReadStringFormValue(r.Form, "type") group := sub.groups[typename] if group == nil { logger.Println("LeaveGroup failed. group type is missing :", r.Form) w.WriteHeader(http.StatusBadRequest) return } gid, ok := common.ReadObjectIDFormValue(r.Form, "gid") if !ok { logger.Println("LeaveGroup failed. gid is missing :", r.Form) w.WriteHeader(http.StatusBadRequest) return } mid, midok := common.ReadObjectIDFormValue(r.Form, "mid") if !midok { logger.Println("LeaveGroup failed. mid is missing") w.WriteHeader(http.StatusBadRequest) return } if err := group.Leave(gid, mid); err != nil { // 둘 중 하나는 있어야지 logger.Println("LeaveGroup failed. group.Leave returns err :", err) w.WriteHeader(http.StatusBadRequest) } } func (sub *subTavern) UpdateMemberDocument(w http.ResponseWriter, r *http.Request) { typename, _ := common.ReadStringFormValue(r.Form, "type") group := sub.groups[typename] if group == nil { logger.Println("DismissGroup failed. type is missing") w.WriteHeader(http.StatusBadRequest) return } midobj, ok := common.ReadObjectIDFormValue(r.Form, "mid") if !ok { logger.Println("UpdateMemberDocument failed. member_id is missing") w.WriteHeader(http.StatusBadRequest) return } gidobj, ok := common.ReadObjectIDFormValue(r.Form, "gid") if !ok { logger.Println("UpdateMemberDocument failed. _id is missing") w.WriteHeader(http.StatusBadRequest) return } var updatedoc bson.M if err := readBsonDoc(r.Body, &updatedoc); err != nil { logger.Error("UpdateMemberDocument failed. body decoding error :", err) w.WriteHeader(http.StatusBadRequest) return } if err := group.UpdateMemberDocument(gidobj, midobj, updatedoc); err != nil { logger.Println("UpdateMemberDocument failed :", err) w.WriteHeader(http.StatusInternalServerError) return } } func (sub *subTavern) DismissGroup(w http.ResponseWriter, r *http.Request) { typename, _ := common.ReadStringFormValue(r.Form, "type") group := sub.groups[typename] if group == nil { logger.Println("DismissGroup failed. type is missing") w.WriteHeader(http.StatusBadRequest) return } gid, ok := common.ReadObjectIDFormValue(r.Form, "gid") if !ok { logger.Println("DismissGroup failed. gid is missing :") w.WriteHeader(http.StatusBadRequest) return } if err := group.Dismiss(gid); err != nil { logger.Error("DismissGroup failed. group.Dismiss returns err :", err) w.WriteHeader(http.StatusInternalServerError) return } } func (sub *subTavern) UpdateGroupDocument(w http.ResponseWriter, r *http.Request) { typename, _ := common.ReadStringFormValue(r.Form, "type") group := sub.groups[typename] if group == nil { logger.Println("UpdateGroupDocument failed. type is missing") w.WriteHeader(http.StatusBadRequest) return } gid, ok := common.ReadObjectIDFormValue(r.Form, "gid") if !ok { logger.Println("UpdateGroupDocument failed. gid is missing") w.WriteHeader(http.StatusBadRequest) return } body, err := io.ReadAll(r.Body) if err != nil { logger.Error("UpdateGroupDocument failed. readBsonDoc err :", err) w.WriteHeader(http.StatusBadRequest) return } if err := group.UpdateGroupDocument(gid, body); err != nil { logger.Error("UpdateGroupDocument failed. group.UpdateGroupDocument returns err :", err) w.WriteHeader(http.StatusBadRequest) return } }