Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions api/calendar.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ func parseEventableResp(events []graphmodels.Eventable) ([]CalendarEvent, error)
Created: e.GetCreatedDateTime(),
EndTime: endTime,
Id: e.GetId(),
ICalUId: e.GetICalUId(),
IsCancelled: e.GetIsCancelled(),
JoinURL: joinURL,
Locations: locations,
Expand Down
41 changes: 36 additions & 5 deletions api/calendar_impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"go.uber.org/zap"

graphmodels "github.com/microsoftgraph/msgraph-sdk-go/models"
"github.com/microsoftgraph/msgraph-sdk-go/users"
)

// (GET /api/calendar/{userID}).
Expand Down Expand Up @@ -135,11 +136,41 @@ func (s Server) GetAPICalendarEvent(w http.ResponseWriter, r *http.Request, para

// Make call to API route and parse events
// Get old meeting data from microsoft
msftMeeting, err := graph.Me().Events().ByEventId(params.MsftID).Get(ctx, nil)
if err != nil {
logger.Error("failed to get meeting data from microsoft", zap.Error(err))
sendError(w, http.StatusBadGateway, "Failed to get meeting data from microsoft")
return
var msftMeeting graphmodels.Eventable
//nolint: nestif // nesting complexity is not too much
if params.IsICalUId {
queryFilter := "iCalUId eq '" + params.MsftID + "'"

// Get old meeting data from microsoft
requestConfig := users.ItemEventsRequestBuilderGetRequestConfiguration{
QueryParameters: &users.ItemEventsRequestBuilderGetQueryParameters{
Filter: &queryFilter,
},
}

var msftMeetingRes graphmodels.EventCollectionResponseable
msftMeetingRes, err = graph.Me().Events().Get(ctx, &requestConfig)
if err != nil {
logger.Error("failed to get meeting data from microsoft", zap.Error(err))
sendError(w, http.StatusBadGateway, "Failed to get meeting data from microsoft")
return
}

if msftMeetingRes != nil && msftMeetingRes.GetValue() != nil &&
len(msftMeetingRes.GetValue()) > 0 {
msftMeeting = msftMeetingRes.GetValue()[0]
} else {
logger.Error("failed to get meeting data from microsoft", zap.Error(err))
sendError(w, http.StatusBadGateway, "Failed to get meeting data from microsoft")
return
}
} else {
msftMeeting, err = graph.Me().Events().ByEventId(params.MsftID).Get(ctx, nil)
if err != nil {
logger.Error("failed to get meeting data from microsoft", zap.Error(err))
sendError(w, http.StatusBadGateway, "Failed to get meeting data from microsoft")
return
}
}

var parsedEvents []CalendarEvent
Expand Down
59 changes: 39 additions & 20 deletions api/reschedule.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
"github.com/avast/retry-go"
msgraphsdkgo "github.com/microsoftgraph/msgraph-sdk-go"
graphmodels "github.com/microsoftgraph/msgraph-sdk-go/models"
"go.uber.org/zap"
"github.com/microsoftgraph/msgraph-sdk-go/users"
)

// durationToISO formats a positive duration in the ISO 8601 format.
Expand Down Expand Up @@ -175,6 +175,7 @@ type NewMeetingAndPrefsParams struct {
func createNewMeetingsAndPrefs(ctx context.Context,
body NewMeetingAndPrefsParams,
s Server,
msftID string,
) (database.Meeting, error) {
// Meeting Info does not exist so create a new one
// Check valid user id
Expand All @@ -198,11 +199,12 @@ func createNewMeetingsAndPrefs(ctx context.Context,
}

// Create Meeting

meetingParams := database.CreateMeetingParams{
//nolint: gosec // id is unsigned 32 bit int
MeetingPrefID: uint32(meetingPrefID),
OwnerEmail: body.OwnerEmail,
MsftMeetingID: body.MsftMeetingID,
MsftMeetingID: msftID,
}

err = retry.Do(func() error {
Expand All @@ -216,7 +218,7 @@ func createNewMeetingsAndPrefs(ctx context.Context,
}

var meeting database.Meeting
meeting, err = s.DB.GetMeetingByMSFTID(ctx, body.MsftMeetingID)
meeting, err = s.DB.GetMeetingByMSFTID(ctx, msftID)
if err != nil {
return database.Meeting{}, err
}
Expand All @@ -228,40 +230,57 @@ func processNewMeetingInfo(ctx context.Context,
graph *msgraphsdkgo.GraphServiceClient,
s Server,
msftMeetingID string,
logger zap.SugaredLogger,
userEmail string,
) (database.Meeting, error) {
// Fetch meeting data from microsft
msftMeeting, err := graph.Me().Events().ByEventId(msftMeetingID).Get(ctx, nil)

msftMeeting, err := getUsersEvent(ctx, graph, msftMeetingID)
if err != nil {
logger.Error("failed to get meeting data from microsoft", zap.Error(err))
return database.Meeting{}, err
return database.Meeting{}, fmt.Errorf("failed to get meeting data from microsoft: %w", err)
}

var startTime time.Time
startTime, err = time.Parse(time.RFC3339Nano, *msftMeeting.GetStart().GetDateTime()+"Z")
if err != nil {
logger.Error("failed to get parse start time", zap.Error(err))
return database.Meeting{}, err
}

// Parse email
var email string
if msftMeeting.GetOrganizer().GetEmailAddress() != nil &&
msftMeeting.GetOrganizer().GetEmailAddress().GetAddress() != nil {
email = *msftMeeting.GetOrganizer().GetEmailAddress().GetAddress()
return database.Meeting{}, fmt.Errorf("failed to get parse start time: %w", err)
}

newMeetingParams := NewMeetingAndPrefsParams{
MeetingStartTime: startTime,
OwnerEmail: email,
OwnerEmail: userEmail,
MsftMeetingID: msftMeetingID,
}

meeting, err := createNewMeetingsAndPrefs(ctx, newMeetingParams, s)
meeting, err := createNewMeetingsAndPrefs(ctx, newMeetingParams, s, msftMeetingID)
if err != nil {
logger.Error("failed to get data from new db.Meeting", zap.Error(err))
return database.Meeting{}, err
return database.Meeting{}, fmt.Errorf("failed to get data from new db.Meeting: %w", err)
}

return meeting, nil
}

func getUsersEvent(ctx context.Context,
graph *msgraphsdkgo.GraphServiceClient,
msftID string,
) (graphmodels.Eventable, error) {
queryFilter := "iCalUId eq '" + msftID + "'"

// Get old meeting data from microsoft
requestConfig := users.ItemEventsRequestBuilderGetRequestConfiguration{
QueryParameters: &users.ItemEventsRequestBuilderGetQueryParameters{
Filter: &queryFilter,
},
}

msftMeetingRes, err := graph.Me().Events().Get(ctx, &requestConfig)
if err != nil {
return nil, fmt.Errorf("failed to get meeting data from microsoft: %w", err)
}

if msftMeetingRes != nil && msftMeetingRes.GetValue() != nil &&
len(msftMeetingRes.GetValue()) > 0 {
return msftMeetingRes.GetValue()[0], nil
}

return nil, errors.New("failed to get meeting data from microsoft: returned empty array")
}
52 changes: 33 additions & 19 deletions api/rescheduling_impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (

"github.com/SlotifyApp/slotify-backend/database"
"github.com/avast/retry-go"
msgraphsdkgo "github.com/microsoftgraph/msgraph-sdk-go"
graphmodels "github.com/microsoftgraph/msgraph-sdk-go/models"
"go.uber.org/zap"
)
Expand Down Expand Up @@ -43,8 +44,17 @@ func (s Server) PostAPIRescheduleCheck(w http.ResponseWriter, r *http.Request) {
return
}

var graphForOwner *msgraphsdkgo.GraphServiceClient
graphForOwner, err = CreateMSFTGraphClient(ctx, s.MSALClient, s.DB, userID)
if err != nil {
logger.Error("failed to create msgraph client", zap.Error(err))
sendError(w, http.StatusBadGateway, "Failed to connect to microsoft graph API")
return
}

// Get old meeting data from microsoft
msftMeeting, err := graph.Me().Events().ByEventId(body.OldMeeting.MsftMeetingID).Get(ctx, nil)
msftMeeting, err := getUsersEvent(ctx, graphForOwner,
body.OldMeeting.MsftMeetingID)
if err != nil {
logger.Error("failed to get meeting data from microsoft", zap.Error(err))
sendError(w, http.StatusBadGateway, "Failed to get meeting data from microsoft")
Expand Down Expand Up @@ -126,15 +136,22 @@ func (s Server) PostAPIRescheduleRequestReplace(w http.ResponseWriter, r *http.R
var body ReschedulingRequestBodySchema
var err error
if err = json.NewDecoder(r.Body).Decode(&body); err != nil {
// TODO: Add zap log for body
logger.Error(ErrUnmarshalBody, zap.Error(err))
sendError(w, http.StatusBadRequest, ErrUnmarshalBody.Error())
return
}

graph, err := CreateMSFTGraphClient(ctx, s.MSALClient, s.DB, userID)
// Check owner exists
ownerObj, err := s.DB.GetUserByEmail(ctx, string(body.OldMeeting.OwnerEmail))
if err != nil {
logger.Error("failed to create msgraph client", zap.Error(err))
logger.Error("failed to get owner obj from db: ", zap.Error(err))
sendError(w, http.StatusBadGateway, "owner is not found as a slotify user")
return
}

graph, err := CreateMSFTGraphClient(ctx, s.MSALClient, s.DB, ownerObj.ID)
if err != nil {
logger.Error("failed to create msgraph client with owner id", zap.Error(err))
sendError(w, http.StatusBadGateway, "Failed to connect to microsoft graph API")
return
}
Expand All @@ -161,7 +178,8 @@ func (s Server) PostAPIRescheduleRequestReplace(w http.ResponseWriter, r *http.R

if errors.Is(err, sql.ErrNoRows) {
// Meeting info not in db, so create new meeting info
meeting, err = processNewMeetingInfo(ctx, graph, s, body.OldMeeting.MsftMeetingID, *logger)
meeting, err = processNewMeetingInfo(ctx, graph, s,
body.OldMeeting.MsftMeetingID, string(body.OldMeeting.OwnerEmail))
if err != nil {
logger.Error("DB Creation Error: ", zap.Error(err))
sendError(w, http.StatusBadGateway, "Failed to create New Meeting Info")
Expand Down Expand Up @@ -249,12 +267,6 @@ func (s Server) PostAPIRescheduleRequestReplace(w http.ResponseWriter, r *http.R
Created: time.Now(),
}

// Get Owner ID
ownerObj, err := s.DB.GetUserByEmail(ctx, meeting.OwnerEmail)
if err != nil {
logger.Error("Failed to get owner user obj: ", zap.Error(err))
}

err = s.NotificationService.SendNotification(ctx, s.Logger, s.DB, []uint32{ownerObj.ID}, notifParam)
if err != nil {
logger.Error("Failed to send notification for reschedule request: ", zap.Error(err))
Expand Down Expand Up @@ -283,7 +295,15 @@ func (s Server) PostAPIRescheduleRequestSingle(w http.ResponseWriter, r *http.Re
return
}

graph, err := CreateMSFTGraphClient(ctx, s.MSALClient, s.DB, userID)
// Check owner exists
ownerObj, err := s.DB.GetUserByEmail(ctx, string(body.OwnerEmail))
if err != nil {
logger.Error("failed to get owner obj from db: ", zap.Error(err))
sendError(w, http.StatusBadGateway, "owner is not found as a slotify user")
return
}

graph, err := CreateMSFTGraphClient(ctx, s.MSALClient, s.DB, ownerObj.ID)
if err != nil {
logger.Error("failed to create msgraph client", zap.Error(err))
sendError(w, http.StatusBadGateway, "Failed to connect to microsoft graph API")
Expand Down Expand Up @@ -314,7 +334,7 @@ func (s Server) PostAPIRescheduleRequestSingle(w http.ResponseWriter, r *http.Re
meeting, err = s.DB.GetMeetingByMSFTID(ctx, body.MsftMeetingID)

if errors.Is(err, sql.ErrNoRows) {
meeting, err = processNewMeetingInfo(ctx, graph, s, body.MsftMeetingID, *logger)
meeting, err = processNewMeetingInfo(ctx, graph, s, body.MsftMeetingID, string(body.OwnerEmail))
if err != nil {
logger.Error("failed to make new meeting info", zap.Error(err))
sendError(w, http.StatusBadGateway, "Failed to make new meeting info")
Expand Down Expand Up @@ -351,12 +371,6 @@ func (s Server) PostAPIRescheduleRequestSingle(w http.ResponseWriter, r *http.Re
Created: time.Now(),
}

// Get Owner ID
ownerObj, err := s.DB.GetUserByEmail(ctx, meeting.OwnerEmail)
if err != nil {
logger.Error("Failed to get owner user obj: ", zap.Error(err))
}

err = s.NotificationService.SendNotification(ctx, s.Logger, s.DB, []uint32{ownerObj.ID}, notifParam)
if err != nil {
logger.Error("Failed to send notification for reschedule request: ", zap.Error(err))
Expand Down
Loading