From d834eb97e6c9486543bbc603a859b88062ee2d86 Mon Sep 17 00:00:00 2001 From: Benjamin Cooke Date: Wed, 18 Sep 2024 14:46:58 -0400 Subject: [PATCH 1/5] adding dialog errors when requests fail, fix panics and add consistency to logs --- server/plugin/api.go | 145 +++++++++++++++++++++------------ server/plugin/create.go | 12 +-- server/plugin/notifications.go | 40 ++++----- 3 files changed, 119 insertions(+), 78 deletions(-) diff --git a/server/plugin/api.go b/server/plugin/api.go index a0f0e3c..ed427b0 100644 --- a/server/plugin/api.go +++ b/server/plugin/api.go @@ -67,6 +67,12 @@ func (e *APIErrorResponse) Error() string { return e.Message } +// This is an error response used in interactive dialogs +type DialogErrorResponse struct { + Error string `json:"error"` + StatusCode int `json:"status_code"` +} + // HTTPHandlerFuncWithUserContext is http.HandleFunc but with a UserContext attached type HTTPHandlerFuncWithUserContext func(c *UserContext, w http.ResponseWriter, r *http.Request) @@ -136,6 +142,13 @@ func (p *Plugin) writeAPIError(w http.ResponseWriter, err *APIErrorResponse) { } } +func (p *Plugin) writeInteractiveDialogError(w http.ResponseWriter, errResponse DialogErrorResponse) { + w.WriteHeader(errResponse.StatusCode) + if err := json.NewEncoder(w).Encode(errResponse); err != nil { + p.client.Log.Warn("can't write api error http response", "err", err.Error()) + } +} + func (p *Plugin) checkAuth(handler http.HandlerFunc, responseType ResponseType) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { userID := r.Header.Get("Mattermost-User-ID") @@ -349,13 +362,18 @@ func (p *Plugin) handleFileCreation(c *Context, w http.ResponseWriter, r *http.R fileCreationParams, request, err := getRawRequestAndFileCreationParams(r) if err != nil { p.API.LogError("Failed to get fileCreationParams", "err", err) - w.WriteHeader(http.StatusBadRequest) + p.writeInteractiveDialogError(w, DialogErrorResponse{Error: "Failed to get file creation parameters", StatusCode: http.StatusBadRequest}) return } ctx := context.Background() conf := p.getOAuthConfig() authToken, err := p.getGoogleUserToken(request.UserId) + if err != nil { + p.API.LogError("Failed to get google user token", "err", err) + p.writeInteractiveDialogError(w, DialogErrorResponse{Error: "Failed to get google user token", StatusCode: http.StatusInternalServerError}) + return + } var fileCreationErr error createdFileID := "" @@ -365,8 +383,8 @@ func (p *Plugin) handleFileCreation(c *Context, w http.ResponseWriter, r *http.R { srv, dErr := docs.NewService(ctx, option.WithTokenSource(conf.TokenSource(ctx, authToken))) if dErr != nil { - p.API.LogError("failed to create google docs client", "err", err) - w.WriteHeader(http.StatusInternalServerError) + p.API.LogError("Failed to create google docs client", "err", dErr) + p.writeInteractiveDialogError(w, DialogErrorResponse{Error: "Failed to create google docs client", StatusCode: http.StatusInternalServerError}) return } doc, dErr := srv.Documents.Create(&docs.Document{ @@ -380,8 +398,8 @@ func (p *Plugin) handleFileCreation(c *Context, w http.ResponseWriter, r *http.R { srv, dErr := slides.NewService(ctx, option.WithTokenSource(conf.TokenSource(ctx, authToken))) if dErr != nil { - p.API.LogError("failed to create google slides client", "err", err) - w.WriteHeader(http.StatusInternalServerError) + p.API.LogError("Failed to create google slides client", "err", dErr) + p.writeInteractiveDialogError(w, DialogErrorResponse{Error: "Failed to create google slides client", StatusCode: http.StatusInternalServerError}) return } slide, dErr := srv.Presentations.Create(&slides.Presentation{ @@ -395,8 +413,8 @@ func (p *Plugin) handleFileCreation(c *Context, w http.ResponseWriter, r *http.R { srv, dErr := sheets.NewService(ctx, option.WithTokenSource(conf.TokenSource(ctx, authToken))) if dErr != nil { - p.API.LogError("failed to create google sheets client", "err", err) - w.WriteHeader(http.StatusInternalServerError) + p.API.LogError("Failed to create google sheets client", "err", dErr) + p.writeInteractiveDialogError(w, DialogErrorResponse{Error: "Failed to create google sheets client", StatusCode: http.StatusInternalServerError}) return } sheet, dErr := srv.Spreadsheets.Create(&sheets.Spreadsheet{ @@ -411,21 +429,21 @@ func (p *Plugin) handleFileCreation(c *Context, w http.ResponseWriter, r *http.R } if fileCreationErr != nil { - p.API.LogError("failed to create google drive file", "err", err) - w.WriteHeader(http.StatusInternalServerError) + p.API.LogError("Failed to create google drive file", "err", fileCreationErr) + p.writeInteractiveDialogError(w, DialogErrorResponse{Error: "Failed to create google drive file", StatusCode: http.StatusInternalServerError}) return } err = p.handleFilePermissions(request.UserId, createdFileID, fileCreationParams.FileAccess, request.ChannelId) if err != nil { - p.API.LogError("failed to modify file permissions", "err", err) - w.WriteHeader(http.StatusInternalServerError) + p.API.LogError("Failed to modify file permissions", "err", err) + p.writeInteractiveDialogError(w, DialogErrorResponse{Error: "Failed to modify file permissions", StatusCode: http.StatusInternalServerError}) return } err = p.sendFileCreatedMessage(request.ChannelId, createdFileID, request.UserId, fileCreationParams.Message, fileCreationParams.ShareInChannel, authToken) if err != nil { - p.API.LogError("failed to send file creation post", "err", err) - w.WriteHeader(http.StatusInternalServerError) + p.API.LogError("Failed to send file creation post", "err", err) + p.writeInteractiveDialogError(w, DialogErrorResponse{Error: "Failed to send file creation post", StatusCode: http.StatusInternalServerError}) return } } @@ -449,7 +467,13 @@ func (p *Plugin) handleDriveWatchNotifications(c *Context, w http.ResponseWriter pageToken := u.Query().Get("pageToken") conf := p.getOAuthConfig() - authToken, _ := p.getGoogleUserToken(userID) + authToken, err := p.getGoogleUserToken(userID) + if err != nil { + p.API.LogError("Failed to get google user token", "err", err) + p.writeInteractiveDialogError(w, DialogErrorResponse{Error: "Failed to get google user token", StatusCode: http.StatusInternalServerError}) + return + } + srv, err := drive.NewService(context.Background(), option.WithTokenSource(conf.TokenSource(context.Background(), authToken))) if err != nil { p.API.LogError("Failed to create Google Drive service", "err", err) @@ -458,13 +482,13 @@ func (p *Plugin) handleDriveWatchNotifications(c *Context, w http.ResponseWriter } changeList, err := srv.Changes.List(pageToken).Fields("*").Do() if err != nil { - p.API.LogError("Failed to fetch google drive changes", "err", err) + p.API.LogError("Failed to fetch Google Drive changes", "err", err) w.WriteHeader(http.StatusInternalServerError) return } if changeList.Changes == nil || len(changeList.Changes) == 0 { - p.API.LogInfo("No google drive changes found", "pageToken", pageToken) + p.API.LogInfo("No Google Drive changes found", "pageToken", pageToken) w.WriteHeader(http.StatusOK) return } @@ -504,7 +528,7 @@ func (p *Plugin) handleDriveWatchNotifications(c *Context, w http.ResponseWriter }).Do() if err != nil { - p.API.LogError("Failed to fetch google drive activity", "fileID", lastChange.FileId) + p.API.LogError("Failed to fetch google drive activity", "err", err, "fileID", lastChange.FileId) w.WriteHeader(http.StatusInternalServerError) return } @@ -528,7 +552,7 @@ func (p *Plugin) handleDriveWatchNotifications(c *Context, w http.ResponseWriter func (p *Plugin) openCommentReplyDialog(c *Context, w http.ResponseWriter, r *http.Request) { requestData, err := io.ReadAll(r.Body) if err != nil { - p.API.LogError("failed to read request body", "err", err) + p.API.LogError("Failed to read request body", "err", err) w.WriteHeader(http.StatusInternalServerError) return } @@ -536,7 +560,7 @@ func (p *Plugin) openCommentReplyDialog(c *Context, w http.ResponseWriter, r *ht var request model.PostActionIntegrationRequest err = json.Unmarshal(requestData, &request) if err != nil { - p.API.LogError("failed to parse request body", "err", err) + p.API.LogError("Failed to parse request body", "err", err) w.WriteHeader(http.StatusInternalServerError) return } @@ -564,7 +588,7 @@ func (p *Plugin) openCommentReplyDialog(c *Context, w http.ResponseWriter, r *ht appErr := p.API.OpenInteractiveDialog(dialog) if appErr != nil { - p.API.LogWarn("Failed to open interactive dialog", "err", err) + p.API.LogWarn("Failed to open interactive dialog", "err", appErr) w.WriteHeader(http.StatusInternalServerError) return } @@ -573,8 +597,8 @@ func (p *Plugin) openCommentReplyDialog(c *Context, w http.ResponseWriter, r *ht func (p *Plugin) handleCommentReplyDialog(c *Context, w http.ResponseWriter, r *http.Request) { requestData, err := io.ReadAll(r.Body) if err != nil { - p.API.LogError("failed to read request body", "err", err) - w.WriteHeader(http.StatusInternalServerError) + p.API.LogError("Failed to read request body", "err", err) + p.writeInteractiveDialogError(w, DialogErrorResponse{Error: "Failed to read request body", StatusCode: http.StatusInternalServerError}) return } defer r.Body.Close() @@ -582,8 +606,8 @@ func (p *Plugin) handleCommentReplyDialog(c *Context, w http.ResponseWriter, r * var request model.SubmitDialogRequest err = json.Unmarshal(requestData, &request) if err != nil { - p.API.LogError("failed to parse request body", "err", err) - w.WriteHeader(http.StatusInternalServerError) + p.API.LogError("Failed to parse request body", "err", err) + p.writeInteractiveDialogError(w, DialogErrorResponse{Error: "Failed to parse request body", StatusCode: http.StatusInternalServerError}) return } @@ -591,19 +615,24 @@ func (p *Plugin) handleCommentReplyDialog(c *Context, w http.ResponseWriter, r * fileID := r.URL.Query().Get("fileID") conf := p.getOAuthConfig() - authToken, _ := p.getGoogleUserToken(request.UserId) + authToken, err := p.getGoogleUserToken(request.UserId) + if err != nil { + p.API.LogError("Failed to get google user token", "err", err) + p.writeInteractiveDialogError(w, DialogErrorResponse{Error: "Failed to get google user token", StatusCode: http.StatusInternalServerError}) + return + } srv, err := drive.NewService(context.Background(), option.WithTokenSource(conf.TokenSource(context.Background(), authToken))) if err != nil { - p.API.LogError("failed to create Drive service", "err", err) - w.WriteHeader(http.StatusInternalServerError) + p.API.LogError("Failed to create Google Drive service", "err", err) + p.writeInteractiveDialogError(w, DialogErrorResponse{Error: "Failed to create Google Drive service", StatusCode: http.StatusInternalServerError}) return } reply, err := srv.Replies.Create(fileID, commentID, &drive.Reply{ Content: request.Submission["message"].(string), }).Fields("*").Do() if err != nil { - p.API.LogError("failed to create comment reply", "err", err) - w.WriteHeader(http.StatusInternalServerError) + p.API.LogError("Failed to create comment reply", "err", err) + p.writeInteractiveDialogError(w, DialogErrorResponse{Error: "Failed to create comment reply", StatusCode: http.StatusInternalServerError}) return } @@ -615,7 +644,7 @@ func (p *Plugin) handleCommentReplyDialog(c *Context, w http.ResponseWriter, r * } _, appErr := p.API.CreatePost(&post) if appErr != nil { - p.API.LogWarn("failed to create post", "err", err, "channelID", post.ChannelId, "rootId", post.RootId, "message", post.Message) + p.API.LogWarn("Failed to create post", "err", appErr, "channelID", post.ChannelId, "rootId", post.RootId, "message", post.Message) w.WriteHeader(http.StatusInternalServerError) return } @@ -626,7 +655,7 @@ func (p *Plugin) handleFileUpload(c *Context, w http.ResponseWriter, r *http.Req err := json.NewDecoder(r.Body).Decode(&request) if err != nil { p.API.LogError("Failed to decode SubmitDialogRequest", "err", err) - w.WriteHeader(http.StatusBadRequest) + p.writeInteractiveDialogError(w, DialogErrorResponse{Error: "Failed to decode request", StatusCode: http.StatusBadRequest}) return } defer r.Body.Close() @@ -634,25 +663,31 @@ func (p *Plugin) handleFileUpload(c *Context, w http.ResponseWriter, r *http.Req fileID := request.Submission["fileID"].(string) fileInfo, appErr := p.API.GetFileInfo(fileID) if appErr != nil { - p.API.LogError("unable to fetch file info", "err", err, "fileID", fileID) - w.WriteHeader(http.StatusInternalServerError) + p.API.LogError("Unable to fetch file info", "err", appErr, "fileID", fileID) + p.writeInteractiveDialogError(w, DialogErrorResponse{Error: "Unable to fetch file info", StatusCode: http.StatusInternalServerError}) return } fileReader, appErr := p.API.GetFile(fileID) if appErr != nil { - p.API.LogError("unable to fetch file data", "err", err, "fileID", fileID) - w.WriteHeader(http.StatusInternalServerError) + p.API.LogError("Unable to fetch file data", "err", appErr, "fileID", fileID) + p.writeInteractiveDialogError(w, DialogErrorResponse{Error: "Unable to fetch file data", StatusCode: http.StatusInternalServerError}) return } ctx := context.Background() conf := p.getOAuthConfig() - authToken, _ := p.getGoogleUserToken(c.UserID) + authToken, err := p.getGoogleUserToken(c.UserID) + if err != nil { + p.API.LogError("Failed to get google user token", "err", err) + p.writeInteractiveDialogError(w, DialogErrorResponse{Error: "Failed to get google user token", StatusCode: http.StatusInternalServerError}) + return + } + srv, err := drive.NewService(ctx, option.WithTokenSource(conf.TokenSource(ctx, authToken))) if err != nil { - p.API.LogError("failed to create drive service", "err", err) - w.WriteHeader(http.StatusInternalServerError) + p.API.LogError("Failed to create Google Drive service", "err", err) + p.writeInteractiveDialogError(w, DialogErrorResponse{Error: "Failed to create Google Drive service", StatusCode: http.StatusInternalServerError}) return } @@ -660,8 +695,8 @@ func (p *Plugin) handleFileUpload(c *Context, w http.ResponseWriter, r *http.Req Name: fileInfo.Name, }).Media(bytes.NewReader(fileReader)).Do() if err != nil { - p.API.LogError("failed to upload file", "err", err) - w.WriteHeader(http.StatusInternalServerError) + p.API.LogError("Failed to upload file", "err", err) + p.writeInteractiveDialogError(w, DialogErrorResponse{Error: "Failed to upload file", StatusCode: http.StatusInternalServerError}) return } @@ -677,7 +712,7 @@ func (p *Plugin) handleAllFilesUpload(c *Context, w http.ResponseWriter, r *http err := json.NewDecoder(r.Body).Decode(&request) if err != nil { p.API.LogError("Failed to decode SubmitDialogRequest", "err", err) - w.WriteHeader(http.StatusBadRequest) + p.writeInteractiveDialogError(w, DialogErrorResponse{Error: "Failed to decode request", StatusCode: http.StatusBadRequest}) return } defer r.Body.Close() @@ -685,19 +720,25 @@ func (p *Plugin) handleAllFilesUpload(c *Context, w http.ResponseWriter, r *http postID := request.State post, appErr := p.API.GetPost(postID) if appErr != nil { - p.API.LogError("Failed to get post", "err", err, "postID", postID) - w.WriteHeader(http.StatusInternalServerError) + p.API.LogError("Failed to get post", "err", appErr, "postID", postID) + p.writeInteractiveDialogError(w, DialogErrorResponse{Error: "Failed to get post", StatusCode: http.StatusInternalServerError}) return } ctx := context.Background() conf := p.getOAuthConfig() - authToken, _ := p.getGoogleUserToken(c.UserID) + authToken, err := p.getGoogleUserToken(c.UserID) + if err != nil { + p.API.LogError("Failed to get google user token", "err", err) + p.writeInteractiveDialogError(w, DialogErrorResponse{Error: "Failed to get google user token", StatusCode: http.StatusInternalServerError}) + return + } + srv, err := drive.NewService(ctx, option.WithTokenSource(conf.TokenSource(ctx, authToken))) if err != nil { - p.API.LogError("failed to create drive service", "err", err) - w.WriteHeader(http.StatusInternalServerError) + p.API.LogError("Failed to create Google Drive service", "err", err) + p.writeInteractiveDialogError(w, DialogErrorResponse{Error: "Failed to create Google Drive service", StatusCode: http.StatusInternalServerError}) return } @@ -705,15 +746,15 @@ func (p *Plugin) handleAllFilesUpload(c *Context, w http.ResponseWriter, r *http for _, fileID := range fileIds { fileInfo, appErr := p.API.GetFileInfo(fileID) if appErr != nil { - p.API.LogError("unable to get file info", "err", err, "fileID", fileID) - w.WriteHeader(http.StatusInternalServerError) + p.API.LogError("Unable to get file info", "err", appErr, "fileID", fileID) + p.writeInteractiveDialogError(w, DialogErrorResponse{Error: "Unable to get file info", StatusCode: http.StatusInternalServerError}) return } fileReader, appErr := p.API.GetFile(fileID) if appErr != nil { - p.API.LogError("unable to get file", "err", err, "fileID", fileID) - w.WriteHeader(http.StatusInternalServerError) + p.API.LogError("Unable to get file", "err", appErr, "fileID", fileID) + p.writeInteractiveDialogError(w, DialogErrorResponse{Error: "Unable to get file", StatusCode: http.StatusInternalServerError}) return } @@ -721,8 +762,8 @@ func (p *Plugin) handleAllFilesUpload(c *Context, w http.ResponseWriter, r *http Name: fileInfo.Name, }).Media(bytes.NewReader(fileReader)).Do() if err != nil { - p.API.LogError("failed to upload file", "err", err) - w.WriteHeader(http.StatusInternalServerError) + p.API.LogError("Failed to upload file", "err", err) + p.writeInteractiveDialogError(w, DialogErrorResponse{Error: "Failed to upload file", StatusCode: http.StatusInternalServerError}) return } } diff --git a/server/plugin/create.go b/server/plugin/create.go index 9b91de6..2dea8d1 100644 --- a/server/plugin/create.go +++ b/server/plugin/create.go @@ -21,12 +21,12 @@ func (p *Plugin) sendFileCreatedMessage(channelID, fileID, userID, message strin conf := p.getOAuthConfig() srv, err := drive.NewService(ctx, option.WithTokenSource(conf.TokenSource(ctx, authToken))) if err != nil { - p.API.LogError("failed to create drive client", "err", err) + p.API.LogError("Failed to create drive client", "err", err) return err } file, err := srv.Files.Get(fileID).Fields("webViewLink", "id", "owners", "permissions", "name", "iconLink", "thumbnailLink", "createdTime").Do() if err != nil { - p.API.LogError("failed to fetch file", "err", err, "fileID", err) + p.API.LogError("Failed to fetch file", "err", err, "fileID", fileID) return err } @@ -49,7 +49,7 @@ func (p *Plugin) sendFileCreatedMessage(channelID, fileID, userID, message strin } _, appErr := p.API.CreatePost(&post) if appErr != nil { - p.API.LogWarn("failed to create post", "err", err, "channelID", post.ChannelId, "rootId", post.RootId, "message", post.Message) + p.API.LogWarn("Failed to create post", "err", appErr, "channelID", post.ChannelId, "rootId", post.RootId, "message", post.Message) return errors.New(appErr.DetailedError) } } else { @@ -131,14 +131,14 @@ func (p *Plugin) handleFilePermissions(userID string, fileID string, fileAccess authToken, _ := p.getGoogleUserToken(userID) srv, err := drive.NewService(ctx, option.WithTokenSource(conf.TokenSource(ctx, authToken))) if err != nil { - p.API.LogError("failed to create drive client", "err", err) + p.API.LogError("Failed to create drive client", "err", err) return err } for _, permission := range permissions { _, err := srv.Permissions.Create(fileID, permission).Do() if err != nil { - p.API.LogError("something went wrong while updating permissions for file", "err", err, "fileID", fileID) + p.API.LogError("Something went wrong while updating permissions for file", "err", err, "fileID", fileID) return err } } @@ -225,7 +225,7 @@ func (p *Plugin) handleCreate(c *plugin.Context, args *model.CommandArgs, parame appErr := p.API.OpenInteractiveDialog(dialog) if appErr != nil { - p.API.LogWarn("failed to open interactive dialog", "err", appErr.DetailedError) + p.API.LogWarn("Failed to open interactive dialog", "err", appErr.DetailedError) return "Failed to open file creation dialog" } return "" diff --git a/server/plugin/notifications.go b/server/plugin/notifications.go index 87f11de..cf80211 100644 --- a/server/plugin/notifications.go +++ b/server/plugin/notifications.go @@ -27,13 +27,13 @@ func (p *Plugin) handleAddedComment(dSrv *drive.Service, fileID, userID string, if len(activity.Targets) == 0 || activity.Targets[0].FileComment == nil || activity.Targets[0].FileComment.LegacyCommentId == "" { - p.API.LogWarn("there is no legacyCommentId present in the activity") + p.API.LogWarn("There is no legacyCommentId present in the activity") return } commentID := activity.Targets[0].FileComment.LegacyDiscussionId comment, err := dSrv.Comments.Get(fileID, commentID).Fields("*").IncludeDeleted(true).Do() if err != nil { - p.API.LogError("failed to get comment by legacyDiscussionId", "err", err, "commentID", commentID) + p.API.LogError("Failed to get comment by legacyDiscussionId", "err", err, "commentID", commentID) return } quotedValue := "" @@ -73,13 +73,13 @@ func (p *Plugin) handleReplyAdded(dSrv *drive.Service, fileID, userID string, ac if len(activity.Targets) == 0 || activity.Targets[0].FileComment == nil || activity.Targets[0].FileComment.LegacyDiscussionId == "" { - p.API.LogWarn("there is no legacyDiscussionId present in the activity") + p.API.LogWarn("There is no legacyDiscussionId present in the activity") return } commentID := activity.Targets[0].FileComment.LegacyDiscussionId comment, err := dSrv.Comments.Get(fileID, commentID).Fields("*").IncludeDeleted(true).Do() if err != nil { - p.API.LogError("failed to get comment by legacyDiscussionId", "err", err, "commentID", commentID) + p.API.LogError("Failed to get comment by legacyDiscussionId", "err", err, "commentID", commentID) return } urlToComment := activity.Targets[0].FileComment.LinkToDiscussion @@ -124,13 +124,13 @@ func (p *Plugin) handleResolvedComment(dSrv *drive.Service, fileID, userID strin if len(activity.Targets) == 0 || activity.Targets[0].FileComment == nil || activity.Targets[0].FileComment.LegacyCommentId == "" { - p.API.LogWarn("there is no legacyCommentId present in the activity") + p.API.LogWarn("There is no legacyCommentId present in the activity") return } commentID := activity.Targets[0].FileComment.LegacyCommentId comment, err := dSrv.Comments.Get(fileID, commentID).Fields("*").IncludeDeleted(true).Do() if err != nil { - p.API.LogError("failed to get comment by legacyCommentId", "err", err, "commentID", commentID) + p.API.LogError("Failed to get comment by legacyCommentId", "err", err, "commentID", commentID) return } urlToComment := activity.Targets[0].FileComment.LinkToDiscussion @@ -142,13 +142,13 @@ func (p *Plugin) handleReopenedComment(dSrv *drive.Service, fileID, userID strin if len(activity.Targets) == 0 || activity.Targets[0].FileComment == nil || activity.Targets[0].FileComment.LegacyDiscussionId == "" { - p.API.LogWarn("there is no legacyDiscussionId present in the activity") + p.API.LogWarn("There is no legacyDiscussionId present in the activity") return } commentID := activity.Targets[0].FileComment.LegacyDiscussionId comment, err := dSrv.Comments.Get(fileID, commentID).Fields("*").IncludeDeleted(true).Do() if err != nil { - p.API.LogError("failed to get comment by legacyDiscussionId", "err", err, "commentID", commentID) + p.API.LogError("Failed to get comment by legacyDiscussionId", "err", err, "commentID", commentID) return } urlToComment := activity.Targets[0].FileComment.LinkToDiscussion @@ -167,7 +167,7 @@ func (p *Plugin) handleCommentNotifications(fileID, userID string, activity *dri conf := p.getOAuthConfig() dSrv, err := drive.NewService(ctx, option.WithTokenSource(conf.TokenSource(ctx, authToken))) if err != nil { - p.API.LogError("failed to create drive service client", "err", err) + p.API.LogError("Failed to create drive service client", "err", err) return } file, _ := dSrv.Files.Get(fileID).Fields("webViewLink", "id", "permissions", "name", "iconLink", "createdTime").Do() @@ -204,12 +204,12 @@ func (p *Plugin) handleFileSharedNotification(fileID, userID string, authToken * conf := p.getOAuthConfig() dSrv, err := drive.NewService(ctx, option.WithTokenSource(conf.TokenSource(ctx, authToken))) if err != nil { - p.API.LogError("failed to create drive service client", "err", err) + p.API.LogError("Failed to create drive service client", "err", err) return } file, err := dSrv.Files.Get(fileID).Fields("webViewLink", "id", "permissions", "name", "iconLink", "createdTime").Do() if err != nil { - p.API.LogError("failed to fetch file", "err", err, "fileID", fileID) + p.API.LogError("Failed to fetch file", "err", err, "fileID", fileID) return } @@ -232,25 +232,25 @@ func (p *Plugin) startDriveWatchChannel(userID string) error { conf := p.getOAuthConfig() authToken, err := p.getGoogleUserToken(userID) if err != nil { - p.API.LogError("failed to get auth token", "err", err) + p.API.LogError("Failed to get auth token", "err", err) return err } srv, err := drive.NewService(ctx, option.WithTokenSource(conf.TokenSource(ctx, authToken))) if err != nil { - p.API.LogError("failed to create drive service client", "err", err) + p.API.LogError("Failed to create drive service client", "err", err) return err } startPageToken, err := srv.Changes.GetStartPageToken().Do() if err != nil { - p.API.LogError("failed to get start page token", "err", err) + p.API.LogError("Failed to get start page token", "err", err) return err } url, err := url.Parse(fmt.Sprintf("%s/plugins/%s/api/v1/webhook", *p.client.Configuration.GetConfig().ServiceSettings.SiteURL, manifest.Id)) if err != nil { - p.API.LogError("failed to parse webhook url", "err", err) + p.API.LogError("Failed to parse webhook url", "err", err) return err } query := url.Query() @@ -271,7 +271,7 @@ func (p *Plugin) startDriveWatchChannel(userID string) error { channel, err := srv.Changes.Watch(startPageToken.StartPageToken, &requestChannel).Do() if err != nil { - p.API.LogError("failed to register watch on drive", "err", err, "requestChannel", requestChannel) + p.API.LogError("Failed to register watch on drive", "err", err, "requestChannel", requestChannel) return err } @@ -283,7 +283,7 @@ func (p *Plugin) startDriveWatchChannel(userID string) error { } _, err = p.client.KV.Set(getWatchChannelDataKey(userID), channelData) if err != nil { - p.API.LogError("failed to set drive change channel data", "userID", userID, "channelData", channelData) + p.API.LogError("Failed to set drive change channel data", "userID", userID, "channelData", channelData) return err } return nil @@ -316,7 +316,7 @@ func (p *Plugin) stopDriveActivityNotifications(userID string) string { var watchChannelData WatchChannelData err := p.client.KV.Get(getWatchChannelDataKey(userID), &watchChannelData) if err != nil { - p.API.LogError("failed to get drive change channel data", "userID", userID) + p.API.LogError("Failed to get drive change channel data", "userID", userID) return "Something went wrong while stopping Google Drive activity notifications. Please contact your organization admin for support." } @@ -331,7 +331,7 @@ func (p *Plugin) stopDriveActivityNotifications(userID string) string { err = p.client.KV.Delete(getWatchChannelDataKey(userID)) if err != nil { - p.API.LogError("failed to delete drive watch channel data", "err", err) + p.API.LogError("Failed to delete drive watch channel data", "err", err) return "Something went wrong while stopping Google Drive activity notifications. Please contact your organization admin for support." } @@ -341,7 +341,7 @@ func (p *Plugin) stopDriveActivityNotifications(userID string) string { }).Do() if err != nil { - p.API.LogError("failed to stop drive change channel", "err", err) + p.API.LogError("Failed to stop drive change channel", "err", err) } return "Successfully disabled Google Drive activity notifications." From 7669d92183048f7d63953338794f6fd6441f3ab1 Mon Sep 17 00:00:00 2001 From: Benjamin Cooke Date: Wed, 18 Sep 2024 15:00:46 -0400 Subject: [PATCH 2/5] logs --- server/plugin/api.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/plugin/api.go b/server/plugin/api.go index ed427b0..d15cf12 100644 --- a/server/plugin/api.go +++ b/server/plugin/api.go @@ -138,14 +138,14 @@ func (p *Plugin) writeAPIError(w http.ResponseWriter, err *APIErrorResponse) { b, _ := json.Marshal(err) w.WriteHeader(err.StatusCode) if _, err := w.Write(b); err != nil { - p.client.Log.Warn("can't write api error http response", "err", err.Error()) + p.client.Log.Warn("Can't write api error http response", "err", err.Error()) } } func (p *Plugin) writeInteractiveDialogError(w http.ResponseWriter, errResponse DialogErrorResponse) { w.WriteHeader(errResponse.StatusCode) if err := json.NewEncoder(w).Encode(errResponse); err != nil { - p.client.Log.Warn("can't write api error http response", "err", err.Error()) + p.client.Log.Warn("Can't write api error http response", "err", err.Error()) } } From b30dfd16c545ad5defd88b141441c9eab806d4cf Mon Sep 17 00:00:00 2001 From: Benjamin Cooke Date: Thu, 19 Sep 2024 12:20:20 -0400 Subject: [PATCH 3/5] change error string and fix another panic --- server/plugin/api.go | 75 +++++++++++++++++++++++++------------------- 1 file changed, 42 insertions(+), 33 deletions(-) diff --git a/server/plugin/api.go b/server/plugin/api.go index d15cf12..fcd8ec2 100644 --- a/server/plugin/api.go +++ b/server/plugin/api.go @@ -144,6 +144,9 @@ func (p *Plugin) writeAPIError(w http.ResponseWriter, err *APIErrorResponse) { func (p *Plugin) writeInteractiveDialogError(w http.ResponseWriter, errResponse DialogErrorResponse) { w.WriteHeader(errResponse.StatusCode) + if errResponse.Error == "" { + errResponse.Error = "Something went wrong, please contact your system administrator" + } if err := json.NewEncoder(w).Encode(errResponse); err != nil { p.client.Log.Warn("Can't write api error http response", "err", err.Error()) } @@ -362,7 +365,7 @@ func (p *Plugin) handleFileCreation(c *Context, w http.ResponseWriter, r *http.R fileCreationParams, request, err := getRawRequestAndFileCreationParams(r) if err != nil { p.API.LogError("Failed to get fileCreationParams", "err", err) - p.writeInteractiveDialogError(w, DialogErrorResponse{Error: "Failed to get file creation parameters", StatusCode: http.StatusBadRequest}) + p.writeInteractiveDialogError(w, DialogErrorResponse{StatusCode: http.StatusBadRequest}) return } @@ -371,7 +374,7 @@ func (p *Plugin) handleFileCreation(c *Context, w http.ResponseWriter, r *http.R authToken, err := p.getGoogleUserToken(request.UserId) if err != nil { p.API.LogError("Failed to get google user token", "err", err) - p.writeInteractiveDialogError(w, DialogErrorResponse{Error: "Failed to get google user token", StatusCode: http.StatusInternalServerError}) + p.writeInteractiveDialogError(w, DialogErrorResponse{StatusCode: http.StatusInternalServerError}) return } @@ -384,37 +387,41 @@ func (p *Plugin) handleFileCreation(c *Context, w http.ResponseWriter, r *http.R srv, dErr := docs.NewService(ctx, option.WithTokenSource(conf.TokenSource(ctx, authToken))) if dErr != nil { p.API.LogError("Failed to create google docs client", "err", dErr) - p.writeInteractiveDialogError(w, DialogErrorResponse{Error: "Failed to create google docs client", StatusCode: http.StatusInternalServerError}) + p.writeInteractiveDialogError(w, DialogErrorResponse{StatusCode: http.StatusInternalServerError}) return } doc, dErr := srv.Documents.Create(&docs.Document{ Title: fileCreationParams.Name, }).Do() + if dErr != nil { + fileCreationErr = dErr + break + } createdFileID = doc.DocumentId - fileCreationErr = dErr - break } case "slide": { srv, dErr := slides.NewService(ctx, option.WithTokenSource(conf.TokenSource(ctx, authToken))) if dErr != nil { p.API.LogError("Failed to create google slides client", "err", dErr) - p.writeInteractiveDialogError(w, DialogErrorResponse{Error: "Failed to create google slides client", StatusCode: http.StatusInternalServerError}) + p.writeInteractiveDialogError(w, DialogErrorResponse{StatusCode: http.StatusInternalServerError}) return } slide, dErr := srv.Presentations.Create(&slides.Presentation{ Title: fileCreationParams.Name, }).Do() + if dErr != nil { + fileCreationErr = dErr + break + } createdFileID = slide.PresentationId - fileCreationErr = dErr - break } case "sheet": { srv, dErr := sheets.NewService(ctx, option.WithTokenSource(conf.TokenSource(ctx, authToken))) if dErr != nil { p.API.LogError("Failed to create google sheets client", "err", dErr) - p.writeInteractiveDialogError(w, DialogErrorResponse{Error: "Failed to create google sheets client", StatusCode: http.StatusInternalServerError}) + p.writeInteractiveDialogError(w, DialogErrorResponse{StatusCode: http.StatusInternalServerError}) return } sheet, dErr := srv.Spreadsheets.Create(&sheets.Spreadsheet{ @@ -422,28 +429,30 @@ func (p *Plugin) handleFileCreation(c *Context, w http.ResponseWriter, r *http.R Title: fileCreationParams.Name, }, }).Do() + if dErr != nil { + fileCreationErr = dErr + break + } createdFileID = sheet.SpreadsheetId - fileCreationErr = dErr - break } } if fileCreationErr != nil { p.API.LogError("Failed to create google drive file", "err", fileCreationErr) - p.writeInteractiveDialogError(w, DialogErrorResponse{Error: "Failed to create google drive file", StatusCode: http.StatusInternalServerError}) + p.writeInteractiveDialogError(w, DialogErrorResponse{StatusCode: http.StatusInternalServerError}) return } err = p.handleFilePermissions(request.UserId, createdFileID, fileCreationParams.FileAccess, request.ChannelId) if err != nil { p.API.LogError("Failed to modify file permissions", "err", err) - p.writeInteractiveDialogError(w, DialogErrorResponse{Error: "Failed to modify file permissions", StatusCode: http.StatusInternalServerError}) + p.writeInteractiveDialogError(w, DialogErrorResponse{StatusCode: http.StatusInternalServerError}) return } err = p.sendFileCreatedMessage(request.ChannelId, createdFileID, request.UserId, fileCreationParams.Message, fileCreationParams.ShareInChannel, authToken) if err != nil { p.API.LogError("Failed to send file creation post", "err", err) - p.writeInteractiveDialogError(w, DialogErrorResponse{Error: "Failed to send file creation post", StatusCode: http.StatusInternalServerError}) + p.writeInteractiveDialogError(w, DialogErrorResponse{StatusCode: http.StatusInternalServerError}) return } } @@ -470,7 +479,7 @@ func (p *Plugin) handleDriveWatchNotifications(c *Context, w http.ResponseWriter authToken, err := p.getGoogleUserToken(userID) if err != nil { p.API.LogError("Failed to get google user token", "err", err) - p.writeInteractiveDialogError(w, DialogErrorResponse{Error: "Failed to get google user token", StatusCode: http.StatusInternalServerError}) + p.writeInteractiveDialogError(w, DialogErrorResponse{StatusCode: http.StatusInternalServerError}) return } @@ -598,7 +607,7 @@ func (p *Plugin) handleCommentReplyDialog(c *Context, w http.ResponseWriter, r * requestData, err := io.ReadAll(r.Body) if err != nil { p.API.LogError("Failed to read request body", "err", err) - p.writeInteractiveDialogError(w, DialogErrorResponse{Error: "Failed to read request body", StatusCode: http.StatusInternalServerError}) + p.writeInteractiveDialogError(w, DialogErrorResponse{StatusCode: http.StatusInternalServerError}) return } defer r.Body.Close() @@ -607,7 +616,7 @@ func (p *Plugin) handleCommentReplyDialog(c *Context, w http.ResponseWriter, r * err = json.Unmarshal(requestData, &request) if err != nil { p.API.LogError("Failed to parse request body", "err", err) - p.writeInteractiveDialogError(w, DialogErrorResponse{Error: "Failed to parse request body", StatusCode: http.StatusInternalServerError}) + p.writeInteractiveDialogError(w, DialogErrorResponse{StatusCode: http.StatusInternalServerError}) return } @@ -618,13 +627,13 @@ func (p *Plugin) handleCommentReplyDialog(c *Context, w http.ResponseWriter, r * authToken, err := p.getGoogleUserToken(request.UserId) if err != nil { p.API.LogError("Failed to get google user token", "err", err) - p.writeInteractiveDialogError(w, DialogErrorResponse{Error: "Failed to get google user token", StatusCode: http.StatusInternalServerError}) + p.writeInteractiveDialogError(w, DialogErrorResponse{StatusCode: http.StatusInternalServerError}) return } srv, err := drive.NewService(context.Background(), option.WithTokenSource(conf.TokenSource(context.Background(), authToken))) if err != nil { p.API.LogError("Failed to create Google Drive service", "err", err) - p.writeInteractiveDialogError(w, DialogErrorResponse{Error: "Failed to create Google Drive service", StatusCode: http.StatusInternalServerError}) + p.writeInteractiveDialogError(w, DialogErrorResponse{StatusCode: http.StatusInternalServerError}) return } reply, err := srv.Replies.Create(fileID, commentID, &drive.Reply{ @@ -632,7 +641,7 @@ func (p *Plugin) handleCommentReplyDialog(c *Context, w http.ResponseWriter, r * }).Fields("*").Do() if err != nil { p.API.LogError("Failed to create comment reply", "err", err) - p.writeInteractiveDialogError(w, DialogErrorResponse{Error: "Failed to create comment reply", StatusCode: http.StatusInternalServerError}) + p.writeInteractiveDialogError(w, DialogErrorResponse{StatusCode: http.StatusInternalServerError}) return } @@ -655,7 +664,7 @@ func (p *Plugin) handleFileUpload(c *Context, w http.ResponseWriter, r *http.Req err := json.NewDecoder(r.Body).Decode(&request) if err != nil { p.API.LogError("Failed to decode SubmitDialogRequest", "err", err) - p.writeInteractiveDialogError(w, DialogErrorResponse{Error: "Failed to decode request", StatusCode: http.StatusBadRequest}) + p.writeInteractiveDialogError(w, DialogErrorResponse{StatusCode: http.StatusBadRequest}) return } defer r.Body.Close() @@ -664,14 +673,14 @@ func (p *Plugin) handleFileUpload(c *Context, w http.ResponseWriter, r *http.Req fileInfo, appErr := p.API.GetFileInfo(fileID) if appErr != nil { p.API.LogError("Unable to fetch file info", "err", appErr, "fileID", fileID) - p.writeInteractiveDialogError(w, DialogErrorResponse{Error: "Unable to fetch file info", StatusCode: http.StatusInternalServerError}) + p.writeInteractiveDialogError(w, DialogErrorResponse{StatusCode: http.StatusInternalServerError}) return } fileReader, appErr := p.API.GetFile(fileID) if appErr != nil { p.API.LogError("Unable to fetch file data", "err", appErr, "fileID", fileID) - p.writeInteractiveDialogError(w, DialogErrorResponse{Error: "Unable to fetch file data", StatusCode: http.StatusInternalServerError}) + p.writeInteractiveDialogError(w, DialogErrorResponse{StatusCode: http.StatusInternalServerError}) return } @@ -680,14 +689,14 @@ func (p *Plugin) handleFileUpload(c *Context, w http.ResponseWriter, r *http.Req authToken, err := p.getGoogleUserToken(c.UserID) if err != nil { p.API.LogError("Failed to get google user token", "err", err) - p.writeInteractiveDialogError(w, DialogErrorResponse{Error: "Failed to get google user token", StatusCode: http.StatusInternalServerError}) + p.writeInteractiveDialogError(w, DialogErrorResponse{StatusCode: http.StatusInternalServerError}) return } srv, err := drive.NewService(ctx, option.WithTokenSource(conf.TokenSource(ctx, authToken))) if err != nil { p.API.LogError("Failed to create Google Drive service", "err", err) - p.writeInteractiveDialogError(w, DialogErrorResponse{Error: "Failed to create Google Drive service", StatusCode: http.StatusInternalServerError}) + p.writeInteractiveDialogError(w, DialogErrorResponse{StatusCode: http.StatusInternalServerError}) return } @@ -696,7 +705,7 @@ func (p *Plugin) handleFileUpload(c *Context, w http.ResponseWriter, r *http.Req }).Media(bytes.NewReader(fileReader)).Do() if err != nil { p.API.LogError("Failed to upload file", "err", err) - p.writeInteractiveDialogError(w, DialogErrorResponse{Error: "Failed to upload file", StatusCode: http.StatusInternalServerError}) + p.writeInteractiveDialogError(w, DialogErrorResponse{StatusCode: http.StatusInternalServerError}) return } @@ -712,7 +721,7 @@ func (p *Plugin) handleAllFilesUpload(c *Context, w http.ResponseWriter, r *http err := json.NewDecoder(r.Body).Decode(&request) if err != nil { p.API.LogError("Failed to decode SubmitDialogRequest", "err", err) - p.writeInteractiveDialogError(w, DialogErrorResponse{Error: "Failed to decode request", StatusCode: http.StatusBadRequest}) + p.writeInteractiveDialogError(w, DialogErrorResponse{StatusCode: http.StatusBadRequest}) return } defer r.Body.Close() @@ -721,7 +730,7 @@ func (p *Plugin) handleAllFilesUpload(c *Context, w http.ResponseWriter, r *http post, appErr := p.API.GetPost(postID) if appErr != nil { p.API.LogError("Failed to get post", "err", appErr, "postID", postID) - p.writeInteractiveDialogError(w, DialogErrorResponse{Error: "Failed to get post", StatusCode: http.StatusInternalServerError}) + p.writeInteractiveDialogError(w, DialogErrorResponse{StatusCode: http.StatusInternalServerError}) return } @@ -731,14 +740,14 @@ func (p *Plugin) handleAllFilesUpload(c *Context, w http.ResponseWriter, r *http authToken, err := p.getGoogleUserToken(c.UserID) if err != nil { p.API.LogError("Failed to get google user token", "err", err) - p.writeInteractiveDialogError(w, DialogErrorResponse{Error: "Failed to get google user token", StatusCode: http.StatusInternalServerError}) + p.writeInteractiveDialogError(w, DialogErrorResponse{StatusCode: http.StatusInternalServerError}) return } srv, err := drive.NewService(ctx, option.WithTokenSource(conf.TokenSource(ctx, authToken))) if err != nil { p.API.LogError("Failed to create Google Drive service", "err", err) - p.writeInteractiveDialogError(w, DialogErrorResponse{Error: "Failed to create Google Drive service", StatusCode: http.StatusInternalServerError}) + p.writeInteractiveDialogError(w, DialogErrorResponse{StatusCode: http.StatusInternalServerError}) return } @@ -747,14 +756,14 @@ func (p *Plugin) handleAllFilesUpload(c *Context, w http.ResponseWriter, r *http fileInfo, appErr := p.API.GetFileInfo(fileID) if appErr != nil { p.API.LogError("Unable to get file info", "err", appErr, "fileID", fileID) - p.writeInteractiveDialogError(w, DialogErrorResponse{Error: "Unable to get file info", StatusCode: http.StatusInternalServerError}) + p.writeInteractiveDialogError(w, DialogErrorResponse{StatusCode: http.StatusInternalServerError}) return } fileReader, appErr := p.API.GetFile(fileID) if appErr != nil { p.API.LogError("Unable to get file", "err", appErr, "fileID", fileID) - p.writeInteractiveDialogError(w, DialogErrorResponse{Error: "Unable to get file", StatusCode: http.StatusInternalServerError}) + p.writeInteractiveDialogError(w, DialogErrorResponse{StatusCode: http.StatusInternalServerError}) return } @@ -763,7 +772,7 @@ func (p *Plugin) handleAllFilesUpload(c *Context, w http.ResponseWriter, r *http }).Media(bytes.NewReader(fileReader)).Do() if err != nil { p.API.LogError("Failed to upload file", "err", err) - p.writeInteractiveDialogError(w, DialogErrorResponse{Error: "Failed to upload file", StatusCode: http.StatusInternalServerError}) + p.writeInteractiveDialogError(w, DialogErrorResponse{StatusCode: http.StatusInternalServerError}) return } } From fde5e70ebf71426f03bd1d3bc095c8cba0645a57 Mon Sep 17 00:00:00 2001 From: Benjamin Cooke Date: Wed, 2 Oct 2024 14:35:39 -0400 Subject: [PATCH 4/5] fix casing --- server/plugin/api.go | 6 +++--- server/plugin/create.go | 2 +- server/plugin/notifications.go | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/server/plugin/api.go b/server/plugin/api.go index fcd8ec2..3333777 100644 --- a/server/plugin/api.go +++ b/server/plugin/api.go @@ -438,7 +438,7 @@ func (p *Plugin) handleFileCreation(c *Context, w http.ResponseWriter, r *http.R } if fileCreationErr != nil { - p.API.LogError("Failed to create google drive file", "err", fileCreationErr) + p.API.LogError("Failed to create Google Drive file", "err", fileCreationErr) p.writeInteractiveDialogError(w, DialogErrorResponse{StatusCode: http.StatusInternalServerError}) return } @@ -528,7 +528,7 @@ func (p *Plugin) handleDriveWatchNotifications(c *Context, w http.ResponseWriter activitySrv, err := driveactivity.NewService(context.Background(), option.WithTokenSource(conf.TokenSource(context.Background(), authToken))) if err != nil { - p.API.LogError("Failed to fetch google drive changes", "err", err) + p.API.LogError("Failed to fetch Google Drive changes", "err", err) w.WriteHeader(http.StatusInternalServerError) return } @@ -537,7 +537,7 @@ func (p *Plugin) handleDriveWatchNotifications(c *Context, w http.ResponseWriter }).Do() if err != nil { - p.API.LogError("Failed to fetch google drive activity", "err", err, "fileID", lastChange.FileId) + p.API.LogError("Failed to fetch Google Drive activity", "err", err, "fileID", lastChange.FileId) w.WriteHeader(http.StatusInternalServerError) return } diff --git a/server/plugin/create.go b/server/plugin/create.go index 2dea8d1..0d58413 100644 --- a/server/plugin/create.go +++ b/server/plugin/create.go @@ -131,7 +131,7 @@ func (p *Plugin) handleFilePermissions(userID string, fileID string, fileAccess authToken, _ := p.getGoogleUserToken(userID) srv, err := drive.NewService(ctx, option.WithTokenSource(conf.TokenSource(ctx, authToken))) if err != nil { - p.API.LogError("Failed to create drive client", "err", err) + p.API.LogError("Failed to create Google Drive client", "err", err) return err } diff --git a/server/plugin/notifications.go b/server/plugin/notifications.go index cf80211..7f63828 100644 --- a/server/plugin/notifications.go +++ b/server/plugin/notifications.go @@ -167,7 +167,7 @@ func (p *Plugin) handleCommentNotifications(fileID, userID string, activity *dri conf := p.getOAuthConfig() dSrv, err := drive.NewService(ctx, option.WithTokenSource(conf.TokenSource(ctx, authToken))) if err != nil { - p.API.LogError("Failed to create drive service client", "err", err) + p.API.LogError("Failed to create Google Drive client", "err", err) return } file, _ := dSrv.Files.Get(fileID).Fields("webViewLink", "id", "permissions", "name", "iconLink", "createdTime").Do() @@ -204,7 +204,7 @@ func (p *Plugin) handleFileSharedNotification(fileID, userID string, authToken * conf := p.getOAuthConfig() dSrv, err := drive.NewService(ctx, option.WithTokenSource(conf.TokenSource(ctx, authToken))) if err != nil { - p.API.LogError("Failed to create drive service client", "err", err) + p.API.LogError("Failed to create Google Drive client", "err", err) return } file, err := dSrv.Files.Get(fileID).Fields("webViewLink", "id", "permissions", "name", "iconLink", "createdTime").Do() @@ -238,7 +238,7 @@ func (p *Plugin) startDriveWatchChannel(userID string) error { srv, err := drive.NewService(ctx, option.WithTokenSource(conf.TokenSource(ctx, authToken))) if err != nil { - p.API.LogError("Failed to create drive service client", "err", err) + p.API.LogError("Failed to create Google Drive client", "err", err) return err } From 881ca7ab74c154c18f838064c62b307ffe99c8cb Mon Sep 17 00:00:00 2001 From: Benjamin Cooke Date: Wed, 2 Oct 2024 14:51:06 -0400 Subject: [PATCH 5/5] fix casing --- README.md | 4 ++-- plugin.json | 2 +- server/plugin/api.go | 18 +++++++++--------- server/plugin/command.go | 6 +++--- server/plugin/configuration.go | 4 ++-- server/plugin/create.go | 2 +- server/plugin/disconnect.go | 4 ++-- server/plugin/notifications.go | 8 ++++---- server/plugin/plugin.go | 6 +++--- 9 files changed, 27 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 74df9cc..a9729a9 100644 --- a/README.md +++ b/README.md @@ -61,8 +61,8 @@ After your System Admin has configured the Google Drive plugin, run `/google-dri | `/google-drive notifications stop` | Disable Google Drive activity notifications. | #### Post menu bindings -`Upload file to Google drive`:: This option is available in any post to upload any attached files directly to your google drive. You will be prompted with a dropdown to choose the attachment you want to upload. -`Upload all files to Google drive`:: This option is available in any post to upload all the attached files directly to your google drive. You will be prompted with a confirmation to upload all the attached files. +`Upload file to Google drive`:: This option is available in any post to upload any attached files directly to your Google Drive. You will be prompted with a dropdown to choose the attachment you want to upload. +`Upload all files to Google drive`:: This option is available in any post to upload all the attached files directly to your Google Drive. You will be prompted with a confirmation to upload all the attached files. #### How do I share feedback on this plugin? diff --git a/plugin.json b/plugin.json index 6e64223..5df830f 100644 --- a/plugin.json +++ b/plugin.json @@ -19,7 +19,7 @@ "bundle_path": "webapp/dist/main.js" }, "settings_schema": { - "header": "The Google Drive plugin for Mattermost allows users to create, share files in Google drive and receive notifications for shared files and comments on files to stay up-to-date. \n \n Instructions for setup are [available here](https://github.com/mattermost-community/mattermost-plugin-google-drive#configuration).", + "header": "The Google Drive plugin for Mattermost allows users to create, share files in Google Drive and receive notifications for shared files and comments on files to stay up-to-date. \n \n Instructions for setup are [available here](https://github.com/mattermost-community/mattermost-plugin-google-drive#configuration).", "footer": "* To report an issue, make a suggestion or a contribution, [check the repository](https://github.com/mattermost-community/mattermost-plugin-google-drive).", "settings": [ { diff --git a/server/plugin/api.go b/server/plugin/api.go index 3333777..3f3bf48 100644 --- a/server/plugin/api.go +++ b/server/plugin/api.go @@ -283,7 +283,7 @@ func (p *Plugin) completeConnectUserToGoogle(c *Context, w http.ResponseWriter, if err != nil { c.Log.WithError(err).Warnf("Can't exchange state") - rErr = errors.Wrap(err, "Failed to exchange oauth code into token") + rErr = errors.Wrap(err, "Failed to exchange OAuth code into token") http.Error(w, rErr.Error(), http.StatusInternalServerError) return } @@ -373,7 +373,7 @@ func (p *Plugin) handleFileCreation(c *Context, w http.ResponseWriter, r *http.R conf := p.getOAuthConfig() authToken, err := p.getGoogleUserToken(request.UserId) if err != nil { - p.API.LogError("Failed to get google user token", "err", err) + p.API.LogError("Failed to get Google user token", "err", err) p.writeInteractiveDialogError(w, DialogErrorResponse{StatusCode: http.StatusInternalServerError}) return } @@ -386,7 +386,7 @@ func (p *Plugin) handleFileCreation(c *Context, w http.ResponseWriter, r *http.R { srv, dErr := docs.NewService(ctx, option.WithTokenSource(conf.TokenSource(ctx, authToken))) if dErr != nil { - p.API.LogError("Failed to create google docs client", "err", dErr) + p.API.LogError("Failed to create Google Docs client", "err", dErr) p.writeInteractiveDialogError(w, DialogErrorResponse{StatusCode: http.StatusInternalServerError}) return } @@ -403,7 +403,7 @@ func (p *Plugin) handleFileCreation(c *Context, w http.ResponseWriter, r *http.R { srv, dErr := slides.NewService(ctx, option.WithTokenSource(conf.TokenSource(ctx, authToken))) if dErr != nil { - p.API.LogError("Failed to create google slides client", "err", dErr) + p.API.LogError("Failed to create Google Slides client", "err", dErr) p.writeInteractiveDialogError(w, DialogErrorResponse{StatusCode: http.StatusInternalServerError}) return } @@ -420,7 +420,7 @@ func (p *Plugin) handleFileCreation(c *Context, w http.ResponseWriter, r *http.R { srv, dErr := sheets.NewService(ctx, option.WithTokenSource(conf.TokenSource(ctx, authToken))) if dErr != nil { - p.API.LogError("Failed to create google sheets client", "err", dErr) + p.API.LogError("Failed to create Google Sheets client", "err", dErr) p.writeInteractiveDialogError(w, DialogErrorResponse{StatusCode: http.StatusInternalServerError}) return } @@ -478,7 +478,7 @@ func (p *Plugin) handleDriveWatchNotifications(c *Context, w http.ResponseWriter conf := p.getOAuthConfig() authToken, err := p.getGoogleUserToken(userID) if err != nil { - p.API.LogError("Failed to get google user token", "err", err) + p.API.LogError("Failed to get Google user token", "err", err) p.writeInteractiveDialogError(w, DialogErrorResponse{StatusCode: http.StatusInternalServerError}) return } @@ -626,7 +626,7 @@ func (p *Plugin) handleCommentReplyDialog(c *Context, w http.ResponseWriter, r * conf := p.getOAuthConfig() authToken, err := p.getGoogleUserToken(request.UserId) if err != nil { - p.API.LogError("Failed to get google user token", "err", err) + p.API.LogError("Failed to get Google user token", "err", err) p.writeInteractiveDialogError(w, DialogErrorResponse{StatusCode: http.StatusInternalServerError}) return } @@ -688,7 +688,7 @@ func (p *Plugin) handleFileUpload(c *Context, w http.ResponseWriter, r *http.Req conf := p.getOAuthConfig() authToken, err := p.getGoogleUserToken(c.UserID) if err != nil { - p.API.LogError("Failed to get google user token", "err", err) + p.API.LogError("Failed to get Google user token", "err", err) p.writeInteractiveDialogError(w, DialogErrorResponse{StatusCode: http.StatusInternalServerError}) return } @@ -739,7 +739,7 @@ func (p *Plugin) handleAllFilesUpload(c *Context, w http.ResponseWriter, r *http authToken, err := p.getGoogleUserToken(c.UserID) if err != nil { - p.API.LogError("Failed to get google user token", "err", err) + p.API.LogError("Failed to get Google user token", "err", err) p.writeInteractiveDialogError(w, DialogErrorResponse{StatusCode: http.StatusInternalServerError}) return } diff --git a/server/plugin/command.go b/server/plugin/command.go index 156ca14..8359e87 100644 --- a/server/plugin/command.go +++ b/server/plugin/command.go @@ -42,9 +42,9 @@ func getAutocompleteData(config *Configuration) *model.AutocompleteData { create.AddCommand(slide) create.AddCommand(sheet) - notifications := model.NewAutocompleteData("notifications", "[command]", "Configure drive activity notifications") - start := model.NewAutocompleteData("start", "", "Start drive activity notifications") - stop := model.NewAutocompleteData("stop", "", "Stop drive activity notifications") + notifications := model.NewAutocompleteData("notifications", "[command]", "Configure Google Drive activity notifications") + start := model.NewAutocompleteData("start", "", "Start Google Drive activity notifications") + stop := model.NewAutocompleteData("stop", "", "Stop Google Drive activity notifications") notifications.AddCommand(start) notifications.AddCommand(stop) drive.AddCommand(notifications) diff --git a/server/plugin/configuration.go b/server/plugin/configuration.go index 1c02e33..5f61bad 100644 --- a/server/plugin/configuration.go +++ b/server/plugin/configuration.go @@ -83,10 +83,10 @@ func (c *Configuration) Clone() *Configuration { // IsValid checks if all needed fields are set. func (c *Configuration) IsValid() error { if c.GoogleOAuthClientID == "" { - return errors.New("must have a google oauth client id") + return errors.New("must have a Google OAuth client id") } if c.GoogleOAuthClientSecret == "" { - return errors.New("must have a google oauth client secret") + return errors.New("must have a Google OAuth client secret") } if c.EncryptionKey == "" { diff --git a/server/plugin/create.go b/server/plugin/create.go index 0d58413..70f7bc9 100644 --- a/server/plugin/create.go +++ b/server/plugin/create.go @@ -21,7 +21,7 @@ func (p *Plugin) sendFileCreatedMessage(channelID, fileID, userID, message strin conf := p.getOAuthConfig() srv, err := drive.NewService(ctx, option.WithTokenSource(conf.TokenSource(ctx, authToken))) if err != nil { - p.API.LogError("Failed to create drive client", "err", err) + p.API.LogError("Failed to create Google Drive client", "err", err) return err } file, err := srv.Files.Get(fileID).Fields("webViewLink", "id", "owners", "permissions", "name", "iconLink", "thumbnailLink", "createdTime").Do() diff --git a/server/plugin/disconnect.go b/server/plugin/disconnect.go index 0d7f3e1..33e3521 100644 --- a/server/plugin/disconnect.go +++ b/server/plugin/disconnect.go @@ -9,11 +9,11 @@ func (p *Plugin) handleDisconnect(c *plugin.Context, args *model.CommandArgs, _ var encryptedToken []byte _ = p.client.KV.Get(getUserTokenKey(args.UserId), &encryptedToken) if len(encryptedToken) == 0 { - return "There is no google account connected to your mattermost account." + return "There is no Google account connected to your Mattermost account." } err := p.client.KV.Delete(getUserTokenKey(args.UserId)) if err != nil { - p.client.Log.Error("Failed to disconnect google account", "error", err) + p.client.Log.Error("Failed to disconnect Google account", "error", err) return "Encountered an error disconnecting Google account." } return "Disconnected your Google account." diff --git a/server/plugin/notifications.go b/server/plugin/notifications.go index 7f63828..7b52ac6 100644 --- a/server/plugin/notifications.go +++ b/server/plugin/notifications.go @@ -283,7 +283,7 @@ func (p *Plugin) startDriveWatchChannel(userID string) error { } _, err = p.client.KV.Set(getWatchChannelDataKey(userID), channelData) if err != nil { - p.API.LogError("Failed to set drive change channel data", "userID", userID, "channelData", channelData) + p.API.LogError("Failed to set Google Drive change channel data", "userID", userID, "channelData", channelData) return err } return nil @@ -316,7 +316,7 @@ func (p *Plugin) stopDriveActivityNotifications(userID string) string { var watchChannelData WatchChannelData err := p.client.KV.Get(getWatchChannelDataKey(userID), &watchChannelData) if err != nil { - p.API.LogError("Failed to get drive change channel data", "userID", userID) + p.API.LogError("Failed to get Google Drive change channel data", "userID", userID) return "Something went wrong while stopping Google Drive activity notifications. Please contact your organization admin for support." } @@ -331,7 +331,7 @@ func (p *Plugin) stopDriveActivityNotifications(userID string) string { err = p.client.KV.Delete(getWatchChannelDataKey(userID)) if err != nil { - p.API.LogError("Failed to delete drive watch channel data", "err", err) + p.API.LogError("Failed to delete Google Drive watch channel data", "err", err) return "Something went wrong while stopping Google Drive activity notifications. Please contact your organization admin for support." } @@ -341,7 +341,7 @@ func (p *Plugin) stopDriveActivityNotifications(userID string) string { }).Do() if err != nil { - p.API.LogError("Failed to stop drive change channel", "err", err) + p.API.LogError("Failed to stop Google Drive change channel", "err", err) } return "Successfully disabled Google Drive activity notifications." diff --git a/server/plugin/plugin.go b/server/plugin/plugin.go index b10e2db..dce989c 100644 --- a/server/plugin/plugin.go +++ b/server/plugin/plugin.go @@ -155,7 +155,7 @@ func (p *Plugin) OnActivate() error { Description: "Created by the Google Drive plugin.", }, pluginapi.ProfileImagePath(filepath.Join("assets", "profile.png"))) if err != nil { - return errors.Wrap(err, "failed to ensure drive bot") + return errors.Wrap(err, "failed to ensure Google Drive bot") } p.BotUserID = botID @@ -163,8 +163,8 @@ func (p *Plugin) OnActivate() error { p.flowManager = p.NewFlowManager() - // google drive watch api doesn't allow indefinite expiry of watch channels - // so we need to refresh(close old channel and start new one) them before they get expired + // Google Drive watch api doesn't allow indefinite expiry of watch channels + // so we need to refresh (close old channel and start new one) them before they get expired p.channelRefreshJob, err = cluster.Schedule(p.API, "refreshDriveWatchChannelsJob", cluster.MakeWaitForInterval(12*time.Hour), p.refreshDriveWatchChannels) if err != nil { return errors.Wrap(err, "failed to create a scheduled recurring job to refresh watch channels")