github.com/masterhung0112/hk_server/v5@v5.0.0-20220302090640-ec71aef15e1c/api4/remote_cluster.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See LICENSE.txt for license information. 3 4 package api4 5 6 import ( 7 "encoding/json" 8 "io" 9 "io/ioutil" 10 "net/http" 11 "time" 12 13 "github.com/masterhung0112/hk_server/v5/audit" 14 "github.com/masterhung0112/hk_server/v5/model" 15 "github.com/masterhung0112/hk_server/v5/services/remotecluster" 16 ) 17 18 func (api *API) InitRemoteCluster() { 19 api.BaseRoutes.RemoteCluster.Handle("/ping", api.RemoteClusterTokenRequired(remoteClusterPing)).Methods("POST") 20 api.BaseRoutes.RemoteCluster.Handle("/msg", api.RemoteClusterTokenRequired(remoteClusterAcceptMessage)).Methods("POST") 21 api.BaseRoutes.RemoteCluster.Handle("/confirm_invite", api.RemoteClusterTokenRequired(remoteClusterConfirmInvite)).Methods("POST") 22 api.BaseRoutes.RemoteCluster.Handle("/upload/{upload_id:[A-Za-z0-9]+}", api.RemoteClusterTokenRequired(uploadRemoteData)).Methods("POST") 23 api.BaseRoutes.RemoteCluster.Handle("/{user_id:[A-Za-z0-9]+}/image", api.RemoteClusterTokenRequired(remoteSetProfileImage)).Methods("POST") 24 } 25 26 func remoteClusterPing(c *Context, w http.ResponseWriter, r *http.Request) { 27 // make sure remote cluster service is enabled. 28 if _, appErr := c.App.GetRemoteClusterService(); appErr != nil { 29 c.Err = appErr 30 return 31 } 32 33 frame, appErr := model.RemoteClusterFrameFromJSON(r.Body) 34 if appErr != nil { 35 c.Err = appErr 36 return 37 } 38 39 if appErr = frame.IsValid(); appErr != nil { 40 c.Err = appErr 41 return 42 } 43 44 remoteId := c.GetRemoteID(r) 45 if remoteId != frame.RemoteId { 46 c.SetInvalidRemoteIdError(frame.RemoteId) 47 return 48 } 49 50 rc, err := c.App.GetRemoteCluster(frame.RemoteId) 51 if err != nil { 52 c.SetInvalidRemoteIdError(frame.RemoteId) 53 return 54 } 55 56 ping, err := model.RemoteClusterPingFromRawJSON(frame.Msg.Payload) 57 if err != nil { 58 c.SetInvalidParam("msg.payload") 59 return 60 } 61 ping.RecvAt = model.GetMillis() 62 63 if metrics := c.App.Metrics(); metrics != nil { 64 metrics.IncrementRemoteClusterMsgReceivedCounter(rc.RemoteId) 65 } 66 67 resp, _ := json.Marshal(ping) 68 w.Write(resp) 69 } 70 71 func remoteClusterAcceptMessage(c *Context, w http.ResponseWriter, r *http.Request) { 72 // make sure remote cluster service is running. 73 service, appErr := c.App.GetRemoteClusterService() 74 if appErr != nil { 75 c.Err = appErr 76 return 77 } 78 79 frame, appErr := model.RemoteClusterFrameFromJSON(r.Body) 80 if appErr != nil { 81 c.Err = appErr 82 return 83 } 84 85 if appErr = frame.IsValid(); appErr != nil { 86 c.Err = appErr 87 return 88 } 89 90 auditRec := c.MakeAuditRecord("remoteClusterAcceptMessage", audit.Fail) 91 defer c.LogAuditRec(auditRec) 92 93 remoteId := c.GetRemoteID(r) 94 if remoteId != frame.RemoteId { 95 c.SetInvalidRemoteIdError(frame.RemoteId) 96 return 97 } 98 99 rc, err := c.App.GetRemoteCluster(frame.RemoteId) 100 if err != nil { 101 c.SetInvalidRemoteIdError(frame.RemoteId) 102 return 103 } 104 auditRec.AddMeta("remoteCluster", rc) 105 106 // pass message to Remote Cluster Service and write response 107 resp := service.ReceiveIncomingMsg(rc, frame.Msg) 108 109 b, errMarshall := json.Marshal(resp) 110 if errMarshall != nil { 111 c.Err = model.NewAppError("remoteClusterAcceptMessage", "api.marshal_error", nil, errMarshall.Error(), http.StatusInternalServerError) 112 return 113 } 114 w.Write(b) 115 } 116 117 func remoteClusterConfirmInvite(c *Context, w http.ResponseWriter, r *http.Request) { 118 // make sure remote cluster service is running. 119 if _, appErr := c.App.GetRemoteClusterService(); appErr != nil { 120 c.Err = appErr 121 return 122 } 123 124 frame, appErr := model.RemoteClusterFrameFromJSON(r.Body) 125 if appErr != nil { 126 c.Err = appErr 127 return 128 } 129 130 if appErr = frame.IsValid(); appErr != nil { 131 c.Err = appErr 132 return 133 } 134 135 auditRec := c.MakeAuditRecord("remoteClusterAcceptInvite", audit.Fail) 136 defer c.LogAuditRec(auditRec) 137 138 remoteId := c.GetRemoteID(r) 139 if remoteId != frame.RemoteId { 140 c.SetInvalidRemoteIdError(frame.RemoteId) 141 return 142 } 143 144 rc, err := c.App.GetRemoteCluster(frame.RemoteId) 145 if err != nil { 146 c.SetInvalidRemoteIdError(frame.RemoteId) 147 return 148 } 149 auditRec.AddMeta("remoteCluster", rc) 150 151 if time.Since(model.GetTimeForMillis(rc.CreateAt)) > remotecluster.InviteExpiresAfter { 152 c.Err = model.NewAppError("remoteClusterAcceptMessage", "api.context.invitation_expired.error", nil, "", http.StatusBadRequest) 153 return 154 } 155 156 confirm, appErr := model.RemoteClusterInviteFromRawJSON(frame.Msg.Payload) 157 if appErr != nil { 158 c.Err = appErr 159 return 160 } 161 162 rc.RemoteTeamId = confirm.RemoteTeamId 163 rc.SiteURL = confirm.SiteURL 164 rc.RemoteToken = confirm.Token 165 166 if _, err := c.App.UpdateRemoteCluster(rc); err != nil { 167 c.Err = err 168 return 169 } 170 171 auditRec.Success() 172 ReturnStatusOK(w) 173 } 174 175 func uploadRemoteData(c *Context, w http.ResponseWriter, r *http.Request) { 176 if !*c.App.Config().FileSettings.EnableFileAttachments { 177 c.Err = model.NewAppError("uploadRemoteData", "api.file.attachments.disabled.app_error", 178 nil, "", http.StatusNotImplemented) 179 return 180 } 181 182 c.RequireUploadId() 183 if c.Err != nil { 184 return 185 } 186 187 auditRec := c.MakeAuditRecord("uploadRemoteData", audit.Fail) 188 defer c.LogAuditRec(auditRec) 189 auditRec.AddMeta("upload_id", c.Params.UploadId) 190 191 us, err := c.App.GetUploadSession(c.Params.UploadId) 192 if err != nil { 193 c.Err = err 194 return 195 } 196 197 if us.RemoteId != c.GetRemoteID(r) { 198 c.Err = model.NewAppError("uploadRemoteData", "api.context.remote_id_mismatch.app_error", 199 nil, "", http.StatusUnauthorized) 200 return 201 } 202 203 info, err := doUploadData(c, us, r) 204 if err != nil { 205 c.Err = err 206 return 207 } 208 209 auditRec.Success() 210 211 if info == nil { 212 w.WriteHeader(http.StatusNoContent) 213 return 214 } 215 216 w.Write([]byte(info.ToJson())) 217 } 218 219 func remoteSetProfileImage(c *Context, w http.ResponseWriter, r *http.Request) { 220 defer io.Copy(ioutil.Discard, r.Body) 221 222 c.RequireUserId() 223 if c.Err != nil { 224 return 225 } 226 227 if *c.App.Config().FileSettings.DriverName == "" { 228 c.Err = model.NewAppError("remoteUploadProfileImage", "api.user.upload_profile_user.storage.app_error", nil, "", http.StatusNotImplemented) 229 return 230 } 231 232 if r.ContentLength > *c.App.Config().FileSettings.MaxFileSize { 233 c.Err = model.NewAppError("remoteUploadProfileImage", "api.user.upload_profile_user.too_large.app_error", nil, "", http.StatusRequestEntityTooLarge) 234 return 235 } 236 237 if err := r.ParseMultipartForm(*c.App.Config().FileSettings.MaxFileSize); err != nil { 238 c.Err = model.NewAppError("remoteUploadProfileImage", "api.user.upload_profile_user.parse.app_error", nil, err.Error(), http.StatusInternalServerError) 239 return 240 } 241 242 m := r.MultipartForm 243 imageArray, ok := m.File["image"] 244 if !ok { 245 c.Err = model.NewAppError("remoteUploadProfileImage", "api.user.upload_profile_user.no_file.app_error", nil, "", http.StatusBadRequest) 246 return 247 } 248 249 if len(imageArray) == 0 { 250 c.Err = model.NewAppError("remoteUploadProfileImage", "api.user.upload_profile_user.array.app_error", nil, "", http.StatusBadRequest) 251 return 252 } 253 254 auditRec := c.MakeAuditRecord("remoteUploadProfileImage", audit.Fail) 255 defer c.LogAuditRec(auditRec) 256 if imageArray[0] != nil { 257 auditRec.AddMeta("filename", imageArray[0].Filename) 258 } 259 260 user, err := c.App.GetUser(c.Params.UserId) 261 if err != nil || !user.IsRemote() { 262 c.SetInvalidUrlParam("user_id") 263 return 264 } 265 auditRec.AddMeta("user", user) 266 267 imageData := imageArray[0] 268 if err := c.App.SetProfileImage(c.Params.UserId, imageData); err != nil { 269 c.Err = err 270 return 271 } 272 273 auditRec.Success() 274 c.LogAudit("") 275 276 ReturnStatusOK(w) 277 }