-
Notifications
You must be signed in to change notification settings - Fork 31
MM-68138 Adding experimental calendar UI sidebar #486
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 11 commits
abd371b
cc04640
3fdb292
d305959
2670a9c
d2481a3
5e1af95
0646a38
6c6cacb
7e87dc2
4e02de1
c47742f
358e018
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,9 +1,10 @@ | ||
| dist | ||
| server/manifest.go | ||
| webapp/src/manifest.ts | ||
| .DS_Store | ||
| .npminstall | ||
| .idea | ||
| bin | ||
|
|
||
| node_modules | ||
| # notice | ||
| .notice-work |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,6 +19,7 @@ import ( | |
| "github.com/mattermost/mattermost-plugin-mscalendar/calendar/store" | ||
| "github.com/mattermost/mattermost-plugin-mscalendar/calendar/utils/bot" | ||
| "github.com/mattermost/mattermost-plugin-mscalendar/calendar/utils/httputils" | ||
| "github.com/mattermost/mattermost-plugin-mscalendar/calendar/utils/tz" | ||
| ) | ||
|
|
||
| const ( | ||
|
|
@@ -82,7 +83,7 @@ func (cep createEventPayload) ToRemoteEvent(loc *time.Location) (*remote.Event, | |
| if cep.Description != "" { | ||
| evt.Body = &remote.ItemBody{ | ||
| Content: cep.Description, | ||
| ContentType: "text/plain", | ||
| ContentType: "text", | ||
| } | ||
| } | ||
| evt.Subject = cep.Subject | ||
|
|
@@ -195,10 +196,17 @@ func (api *api) createEvent(w http.ResponseWriter, r *http.Request) { | |
| return | ||
| } | ||
|
|
||
| loc, errLocation := time.LoadLocation(mailbox.TimeZone) | ||
| tzName := tz.Go(mailbox.TimeZone) | ||
| if tzName == "" && mailbox.TimeZone != "" { | ||
| errTz := fmt.Errorf("unknown time zone %q", mailbox.TimeZone) | ||
| api.Logger.With(bot.LogContext{"err": errTz.Error(), "timezone": mailbox.TimeZone}).Errorf("createEvent, error occurred while loading mailbox timezone location") | ||
| httputils.WriteInternalServerError(w, errTz) | ||
| return | ||
| } | ||
| loc, errLocation := time.LoadLocation(tzName) | ||
| if errLocation != nil { | ||
| api.Logger.With(bot.LogContext{"err": errLocation.Error(), "timezone": mailbox.TimeZone}).Errorf("createEvent, error occurred while loading mailbox timezone location") | ||
| httputils.WriteInternalServerError(w, errLocation) | ||
| api.Logger.With(bot.LogContext{"err": errLocation.Error(), "timezone": mailbox.TimeZone, "converted": tzName}).Errorf("createEvent, error occurred while loading mailbox timezone location") | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Both error paths pass the raw error to WriteInternalServerError. The errTz includes the user's timezone string which is fine, but errLocation from time.LoadLocation can expose Go runtime details. Should return a generic message to the client. |
||
| httputils.WriteInternalServerError(w, fmt.Errorf("unable to resolve mailbox timezone")) | ||
| return | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,81 @@ | ||
| // Copyright (c) 2019-present Mattermost, Inc. All Rights Reserved. | ||
| // See LICENSE.txt for license information. | ||
|
|
||
| package api | ||
|
|
||
| import ( | ||
| "errors" | ||
| "fmt" | ||
| "net/http" | ||
| "time" | ||
|
|
||
| "github.com/mattermost/mattermost-plugin-mscalendar/calendar/engine" | ||
| "github.com/mattermost/mattermost-plugin-mscalendar/calendar/remote" | ||
| "github.com/mattermost/mattermost-plugin-mscalendar/calendar/store" | ||
| "github.com/mattermost/mattermost-plugin-mscalendar/calendar/utils/bot" | ||
| "github.com/mattermost/mattermost-plugin-mscalendar/calendar/utils/httputils" | ||
| ) | ||
|
|
||
| func (api *api) viewEvents(w http.ResponseWriter, r *http.Request) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This new endpoint has a lot of new code paths and zero tests. Needs a TestViewEvents table covering at least: missing header, missing params, invalid date, from after to, range > 62 days, store.ErrNotFound, engine error, happy path. |
||
| mattermostUserID := r.Header.Get("Mattermost-User-Id") | ||
| if mattermostUserID == "" { | ||
| api.Logger.Errorf("viewEvents, unauthorized user") | ||
| httputils.WriteUnauthorizedError(w, fmt.Errorf("unauthorized")) | ||
| return | ||
| } | ||
|
|
||
| fromStr := r.URL.Query().Get("from") | ||
| toStr := r.URL.Query().Get("to") | ||
| if fromStr == "" || toStr == "" { | ||
| httputils.WriteBadRequestError(w, fmt.Errorf("from and to query parameters are required")) | ||
| return | ||
| } | ||
|
|
||
| from, err := time.Parse(time.RFC3339, fromStr) | ||
| if err != nil { | ||
| httputils.WriteBadRequestError(w, fmt.Errorf("invalid from parameter: %w", err)) | ||
| return | ||
| } | ||
|
|
||
| to, err := time.Parse(time.RFC3339, toStr) | ||
| if err != nil { | ||
| httputils.WriteBadRequestError(w, fmt.Errorf("invalid to parameter: %w", err)) | ||
| return | ||
| } | ||
|
|
||
| if from.After(to) { | ||
| httputils.WriteBadRequestError(w, fmt.Errorf("from must be before or equal to to")) | ||
| return | ||
| } | ||
|
|
||
| const maxWindow = 62 * 24 * time.Hour | ||
| if to.Sub(from) > maxWindow { | ||
| httputils.WriteBadRequestError(w, fmt.Errorf("date range must not exceed 62 days")) | ||
| return | ||
| } | ||
|
|
||
| eng := engine.New(api.Env, mattermostUserID) | ||
| user := engine.NewUser(mattermostUserID) | ||
|
|
||
| events, err := eng.ViewCalendar(user, from, to) | ||
| if err != nil { | ||
| if errors.Is(err, store.ErrNotFound) { | ||
| api.Logger.With(bot.LogContext{"err": err.Error()}).Errorf("viewEvents, user not found in store") | ||
| httputils.WriteUnauthorizedError(w, fmt.Errorf("unauthorized")) | ||
| return | ||
| } | ||
| api.Logger.With(bot.LogContext{"err": err.Error()}).Errorf("viewEvents, error fetching calendar events") | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The raw err which could contain store driver details, remote API errors, etc. is passed directly to the client. |
||
| httputils.WriteInternalServerError(w, fmt.Errorf("error fetching calendar events")) | ||
| return | ||
| } | ||
|
|
||
| if events == nil { | ||
| events = []*remote.Event{} | ||
| } | ||
|
|
||
| for _, e := range events { | ||
| remote.NormalizeDateTimeToRFC3339(e) | ||
| } | ||
|
|
||
| httputils.WriteJSONResponse(w, events, http.StatusOK) | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
verify this doesn't break if the Google Calendar provider expects "text/plain".