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  }