diff --git a/functions/triggers/outlook/README.md b/functions/triggers/outlook/README.md deleted file mode 100644 index c1c5db5d..00000000 --- a/functions/triggers/outlook/README.md +++ /dev/null @@ -1,57 +0,0 @@ -# Outlook trigger -Makes it possible to trigger a workflow based on an email - -## Local testing - Same as ../webhook -```bash -mv ../main.go -go run main.go hook.go -``` - -# Deploy gcloud -gcloud functions deploy outlooktrigger --runtime go111 --entry-point Authorization --trigger-http --project shuffler --memory=128 --set-env-vars=FUNCTION_APIKEY=asdasd,CALLBACKURL=shuffler.io,TRIGGERID=test123,WORKFLOW_ID=YOUR_WORKFLOW_ID - -# Build and deploy -1. Set hook.go line 1 from "package main" to "package function" -2. zip outlooktrigger.tar hook.go -3. Upload to bucket https://console.cloud.google.com/storage/browser/shuffler.appspot.com?project=shuffler -4. Go to the functions https://console.cloud.google.com/functions/list?project=shuffler - - -## How it works (from frontend to backend) -### Choose mailfolders -1. Use microsoft graph api to get the folders the user wants to listen to -* Have the user write their primary email (default) or another one -* Have it show the folders for the email with chooseable buttons somehow -|inbox -|-subinbox -|--subsubinbox <-- choose e.g. this one -|otherfolder - -API: -// requestUrl := fmt.Sprintf("https://graph.microsoft.com/v1.0/users/me/mailfolders") - -### Add callback subscription -2. Make an APIcall to ("https://outlook.office.com/api/v2.0/me/mailfolders('inbox')/messages") with callback url defined as "https://shuffler.io/api/v1/workflows/{key}/email/authorize" -* Should this be set up whenever the user clicked start or when the workflow is created? -* Start click -> -1. Add another cloud function for the item -2. When it's ready, deploy it to authorize -3. Show it as ready - -### Remove a subscription -* Since everything is already generated above, one would need to -* https://docs.microsoft.com/en-us/graph/api/subscription-delete?view=graph-rest-1.0&tabs=http -* DELETE https://graph.microsoft.com/v1.0/subscriptions/{id} - - -## CREATE - Fixme: LIST all current subscriptions, and stop them if they're towards the same endpoint -* POST /api/v1/workflows/{key}/outlook -* createOutlookSub(resp, request) -* getOutlookSubscriptions(client) // Used to remove all existing for same endpoint -* makeOutlookSubscription(client, folderIds, notificationUrl) -* Add data from ^ to triggerAuth - -## DELETE -* DELETE /api/v1/workflows/{key}/outlook/{triggerId} -* handleDeleteOutlookSub(resp, request) -* handleOutlookSubRemoval(workflowId, triggerId) diff --git a/functions/triggers/outlook/hook.go b/functions/triggers/outlook/hook.go deleted file mode 100644 index 9762c2c2..00000000 --- a/functions/triggers/outlook/hook.go +++ /dev/null @@ -1,222 +0,0 @@ -package function - -// Shuffle: -// https://portal.azure.com/#blade/Microsoft_AAD_RegisteredApps/ApplicationMenuBlade/Authentication/appId/e080cbf4-5dba-44b4-8643-a7c982189c16/isMSAApp//defaultBlade/Overview/servicePrincipalCreated/true - -// Oauth playground: -// https://oauthplay.azurewebsites.net/ - -// APPS: -// https://apps.dev.microsoft.com - -// REMOVE ACCESS: -// https://portal.office.com/account/# - -// Developer: -// https://developer.microsoft.com/en-us/graph/docs/concepts/permissions_reference - -// Bots: -// https://dev.botframework.com/bots - -// Connectors -// https://outlook.office.com/connectors/home/login/#/new -// https://go.microsoft.com/fwlink/?linkid=857599 - -import ( - //"encoding/json" - "bytes" - "fmt" - "io/ioutil" - "log" - "net/http" - "os" - "time" -) - -type Info struct { - Url string `json:"url" datastore:"url"` - Name string `json:"name" datastore:"name"` - Description string `json:"description" datastore:"description"` -} - -// Actions to be done by webhooks etc -// Field is the actual field to use from json -type HookAction struct { - Type string `json:"type" datastore:"type"` - Name string `json:"name" datastore:"name"` - Id string `json:"id" datastore:"id"` - Field string `json:"field" datastore:"field"` -} - -type Hook struct { - Id string `json:"id" datastore:"id"` - Info Info `json:"info" datastore:"info"` - Actions []HookAction `json:"actions" datastore:"actions"` - Type string `json:"type" datastore:"type"` - Status string `json:"status" datastore:"status"` - Running bool `json:"running" datastore:"running"` -} - -type TeamsHook struct { - MembersAdded []struct { - ID string `json:"id"` - } `json:"membersAdded"` - Type string `json:"type"` - Timestamp time.Time `json:"timestamp"` - LocalTimestamp string `json:"localTimestamp"` - ID string `json:"id"` - ChannelID string `json:"channelId"` - ServiceURL string `json:"serviceUrl"` - From struct { - ID string `json:"id"` - Name string `json:"name"` - } `json:"from"` - Conversation struct { - IsGroup bool `json:"isGroup"` - ConversationType string `json:"conversationType"` - ID string `json:"id"` - TenantID string `json:"tenantId"` - } `json:"conversation"` - Recipient struct { - ID string `json:"id"` - Name string `json:"name"` - } `json:"recipient"` - ChannelData struct { - Team struct { - ID string `json:"id"` - } `json:"team"` - EventType string `json:"eventType"` - Tenant struct { - ID string `json:"id"` - } `json:"tenant"` - } `json:"channelData"` -} - -var hook Hook -var baseUrl = "https://shuffler.io" - -type OauthToken struct { - TokenType string `json:"token_type"` - ExpiresIn int `json:"expires_in"` - ExtExpiresIn int `json:"ext_expires_in"` - AccessToken string `json:"access_token"` -} - -type TeamsResponse struct { - Conversation struct { - ID string `json:"id"` - } `json:"conversation"` - From struct { - ID string `json:"id"` - Name string `json:"name"` - } `json:"from"` - Recipient struct { - ID string `json:"id"` - Name string `json:"name"` - } `json:"recipient"` - ReplyToId string `json:"replyToId"` - Type string `json:"type"` - Text string `json:"text"` -} - -type O365hook struct { - OdataContext string `json:"@odata.context"` - Value []struct { - OdataType string `json:"@odata.type"` - ID interface{} `json:"Id"` - SubscriptionID string `json:"SubscriptionId"` - SubscriptionExpirationDateTime time.Time `json:"SubscriptionExpirationDateTime"` - SequenceNumber int `json:"SequenceNumber"` - ChangeType string `json:"ChangeType"` - Resource string `json:"Resource"` - ResourceData struct { - OdataType string `json:"@odata.type"` - OdataID string `json:"@odata.id"` - OdataEtag string `json:"@odata.etag"` - ID string `json:"Id"` - } `json:"ResourceData"` - } `json:"value"` -} - -func Authorization(resp http.ResponseWriter, request *http.Request) { - body, err := ioutil.ReadAll(request.Body) - if err != nil { - log.Printf("Body: %s", err) - resp.WriteHeader(403) - return - } - - if len(body) > 0 { - // In here - get the email data - // Check who it belongs to and run those workflows - // This should be set from run.go with the callback - // userId: {subscriptionID: {workflowID}} - // E.g. workflow: {auth: {userId - // workflow: {trigger: { - - err = forwardRequest(body) - if err != nil { - log.Printf("Failed unmarshal: %s", err) - resp.WriteHeader(403) - return - } - - resp.WriteHeader(200) - resp.Write([]byte("OK")) - return - } - - token := request.URL.Query().Get("validationToken") - if len(token) == 0 { - log.Println("Validation token is missing") - resp.WriteHeader(403) - return - } - - resp.WriteHeader(200) - resp.Write([]byte(string(token))) -} - -// GetUserDetails - Get one user's details from randomuser.me API -func forwardRequest(body []byte) error { - callbackUrl := os.Getenv("CALLBACKURL") - workflowId := os.Getenv("WORKFLOW_ID") - apikey := os.Getenv("FUNCTION_APIKEY") - - fullUrl := fmt.Sprintf("%s/api/v1/workflows/%s/execute", callbackUrl, workflowId) - //log.Printf("Sending data to %s", fullUrl) - - data := fmt.Sprintf(`{"execution_argument": "%s"}`, string(body)) - - req, err := http.NewRequest( - http.MethodPost, - fullUrl, - bytes.NewBuffer([]byte(data)), - ) - - if err != nil { - return err - } - - req.Header.Add("Authorization", fmt.Sprintf(`Bearer %s`, apikey)) - req.Header.Add("Content-Type", "application/json") - randomUserClient := http.Client{ - Timeout: time.Second * 5, - } - - res, err := randomUserClient.Do(req) - if err != nil { - return err - } - - log.Printf("Status: %d", res.StatusCode) - returnbody, err := ioutil.ReadAll(res.Body) - if err != nil { - return err - } - - log.Printf("New body: %s", string(returnbody)) - - //log.Println(string(newbody)) - return nil -} diff --git a/functions/triggers/outlook/integrations/config.json b/functions/triggers/outlook/integrations/config.json deleted file mode 100644 index 8d98dba3..00000000 --- a/functions/triggers/outlook/integrations/config.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "clientID": "70e37005-c954-4290-b573-d4b94e484336", - "clientSecret": ".eNw/A[kQFB5zL.agvRputdEJENeJ392", - "RedirectURL": "https://44d84ee7.ngrok.io/functions/outlook/register", - "AuthURL": "https://login.microsoftonline.com/common/oauth2/authorize", - "TokenURL": "https://login.microsoftonline.com/common/oauth2/token" -} diff --git a/functions/triggers/outlook/integrations/server.crt b/functions/triggers/outlook/integrations/server.crt deleted file mode 100644 index 92244399..00000000 --- a/functions/triggers/outlook/integrations/server.crt +++ /dev/null @@ -1,21 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDYDCCAkigAwIBAgIJAOvgxcclM1eyMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV -BAYTAk5PMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX -aWRnaXRzIFB0eSBMdGQwHhcNMTgwMzA1MTE1MTIwWhcNMjgwMzAyMTE1MTIwWjBF -MQswCQYDVQQGEwJOTzETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50 -ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB -CgKCAQEAowNqrvocJCLLcytYBfZhsqG3CkPsJ4PTicNyjuUGmlILPHlN1DE7jbDo -KuOKImfV4AfQANnttaPksZyuKJL8XGpC7YmF5mmInUWG48SmZjvRbBi1LnCrjJKS -ywh2lJqw4w30w2ItcpogDrYhh6+T3VyabcYngZjKSFgON3wo4I0c6aT19VVXGqnK -y1WEejZmiChV4iwEu4vMPIzt16QpIBr8NPSkBLLRDAGWMjFnIuYDEwgjVn6XYhM9 -+NxhvY9es+qeqLQsZj2a1wcDGaw7G4iNZdltlPmlTCreRDBYBTsYCds/rJmPZ2xi -6jgiyNZj3xHG5Knw2YIw0OwHyT9mWQIDAQABo1MwUTAdBgNVHQ4EFgQUckr5tCzg -F1eBID7mtWTfeqyX4g0wHwYDVR0jBBgwFoAUckr5tCzgF1eBID7mtWTfeqyX4g0w -DwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAAdH1aPcWBjJHF6n/ -NgIiRSEU4mi5I6RUlPuR7dN7dcmF1Ho7quurNFzknXwks+a62oKSnkkFxxwrv/d6 -dIH5kNibVs7oRxEpA3gUmXXKUW4RPrxAp2zN37t7zs5xbpTATxfJiIMP8Rjo0sOf -SilS22Sn0e0HxBi78t3DJEZvOQ9KSRuD1g9gOAY4lj/fni6rVJo8YCR2MyjmQoXB -luHDF4jTqi/TkXECfqQZu0pctx3maISpB1fAuaELwPDvqbLgoC97gl6bIEiKLkJ0 -JkbGnb997K80ztFvFAKGyUtsvEDCupe/fdBPFqCruAQWI/BqVJFTdRD43dWEQANF -S8ApvA== ------END CERTIFICATE----- diff --git a/functions/triggers/outlook/integrations/server.key b/functions/triggers/outlook/integrations/server.key deleted file mode 100644 index 87c60e08..00000000 --- a/functions/triggers/outlook/integrations/server.key +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEowIBAAKCAQEAowNqrvocJCLLcytYBfZhsqG3CkPsJ4PTicNyjuUGmlILPHlN -1DE7jbDoKuOKImfV4AfQANnttaPksZyuKJL8XGpC7YmF5mmInUWG48SmZjvRbBi1 -LnCrjJKSywh2lJqw4w30w2ItcpogDrYhh6+T3VyabcYngZjKSFgON3wo4I0c6aT1 -9VVXGqnKy1WEejZmiChV4iwEu4vMPIzt16QpIBr8NPSkBLLRDAGWMjFnIuYDEwgj -Vn6XYhM9+NxhvY9es+qeqLQsZj2a1wcDGaw7G4iNZdltlPmlTCreRDBYBTsYCds/ -rJmPZ2xi6jgiyNZj3xHG5Knw2YIw0OwHyT9mWQIDAQABAoIBABJ+9L/dyQuglwz+ -QgKLLhKinq4fftAM+ReMgZcNDW69GGFIMjh9TZCKHg2fu7Cjr3S37jXqhDoz2mL8 -sBYSd2fU9rsU+4hlOQb/OIrnaSn4Z46oTwZx6kUM7HL1Bt9dnexlTPxOS3HRYwnI -SI2oslJPi4YhEaJ2v5ztwM8y20B/E/zSW2onWz5gB8/bdxSmuJaWfHioIEoac8Gf -BE7jiYMnx9kKeVfgkKPMBKXhAyE2lbAz7N5nDS/4HkbUMh389RBvakc4gkv/QkSW -LNuXpbcSqJiG0FcVutjYS87a/ul3IdhAYmZDTuvRUhNsWBiY3LSY4C9NlHhiJihg -RU1kknECgYEA1dPT6n4hy/OK2mT3ThGQQFMJWsnmcHSsvuK31+UYZOI9kNtBVxc6 -HSHkh0G53o6o2wZLr2gMXy35O5ZxSbectA1Q4MJDlYBs1MfHdOVyE4z6mmA9TLN1 -c+9pYOC0qx+6NwPdO7j2xdUMEUfzocWOeay0AzJg20BQYmKuy3Kc+tcCgYEAwyn6 -n+XS0vodfJdHhvbW/jocQlHQOBK5HklZfq2PMgpRRDaBOvHP/f07egLc2inec2sC -yPSCEfRMMhFcU5NoBt4Unzz2Y8pbpL1L5kbM6B4IqK/5vYcbvkmBkhL3AFT6Fg/3 -3XCdygPW9Vf1nRKr2KhT9dDvB+XO2B75JmKwMk8CgYApKzGf8kz7gZZ4WfwrccI+ -QD6K1lihyjUAQ5J15Mv/kHeeDjjUVcqAlWf0irkImpr0IJAt43COWsGjsWF6efmX -yQCLZZuxixppFVXXsd122ivd0S28OMkiWzQEzP67+83Ujc/okcIhcNVz9lB4ExtN -Xe0CuI5haE6RwsI4tYZ33QKBgFq6ckPRcOAZ3IlmPp9Us3/+fdKq/BSFR7/3s347 -q11FBKCkghFoBxx5lCPVntxhKIQZlHLdkHZOTvnbrkNAPNUsewPIMHcVxOLiCZ3k -/i9OfxIEtSJR5CjjPTQuUtu5pYWKKN2uE/ytKkpmeM1rt64CGv4lAmp2gGFijMs2 -h9jrAoGBANPQO6cKqtnxvst3lnljVBoftlJgeHamUac+xeYKA5Hocv5VwLXMTzzu -09tAhQFvFwCWWrfdgtvIM6k5Sl9F5MdiO9VNflI0IVudIcm9FKorWogH02mtwxsw -hvk5VUk3awiZ/Nu9t38ukeqCetjQEf6yupy/14ZPLndN5naSeEwo ------END RSA PRIVATE KEY----- diff --git a/functions/triggers/outlook/main.go b/functions/triggers/outlook/main.go deleted file mode 100644 index 12bc84b3..00000000 --- a/functions/triggers/outlook/main.go +++ /dev/null @@ -1,41 +0,0 @@ -package main - -import ( - "log" - "net/http" - "os" - - "github.com/gorilla/handlers" - "github.com/gorilla/mux" -) - -func webhook() { - // FIXME - remove static - port := ":8080" - baseFilePath := "/" - - mux := mux.NewRouter() - mux.SkipClean(true) - - // FIXME - Add path for updating the hook? Can be a specific POST requeuest from backend - mux.HandleFunc(baseFilePath, Authorization).Methods("POST") - mux.HandleFunc("/authorize", Authorization).Methods("POST") - - handlers.LoggingHandler(os.Stdout, mux) - loggedRouter := handlers.LoggingHandler(os.Stdout, mux) - - log.Printf("Starting on http://localhost%s", port) - err := http.ListenAndServe( - port, - loggedRouter, - ) - - if err != nil { - log.Fatal("ListenAndServer: ", err) - } - -} - -func main() { - webhook() -} diff --git a/functions/triggers/outlook/run.go b/functions/triggers/outlook/run.go deleted file mode 100644 index 55d3d420..00000000 --- a/functions/triggers/outlook/run.go +++ /dev/null @@ -1,304 +0,0 @@ -package main - -// This entire script should be part of the API backend - -import ( - "bytes" - "context" - "encoding/json" - "fmt" - "io/ioutil" - "log" - "net/http" - "time" - - "golang.org/x/oauth2" -) - -type Subscription struct { - ChangeType string `json:"changeType"` - NotificationURL string `json:"notificationUrl"` - Resource string `json:"resource"` - ExpirationDateTime string `json:"expirationDateTime"` - ClientState string `json:"clientState"` -} - -// ClientState string `json:"ClientState,omitempty"` -// OdataType string `json:"@odata.type"` - -//odata.type - Include "@odata.type":"#Microsoft.OutlookServices.PushSubscription". The PushSubscription entity defines NotificationURL. -//ChangeType - Specifies the types of events to monitor for that resource. See ChangeType for the supported types. -//ClientState - Optional property that indicates that each notification should be sent with a header by the same ClientState value. This lets the listener check the legitimacy of each notification. -//NotificationURL - Specifies where notifications should be sent to. This URL represents a web service typically implemented by the client. -//Resource - Specifies the resource to monitor and receive notifications on. You can use the optional query parameter $filter to refine the conditions for a notification, or use $select to include specific properties in a rich notification. - -//https://outlook.office.com/mail.read - -type Config struct { - ClientID string - ClientSecret string - RedirectUrl string - AuthUrl string - TokenUrl string -} - -func getOfficeAppInfo() (Config, error) { - configpath := "integrations/config.json" - - data, err := ioutil.ReadFile(configpath) - if err != nil { - //log.Fatal(err) - log.Printf("Error getting hive: %s\n", err) - } - - config := Config{} - err = json.Unmarshal(data, &config) - if err != nil { - return Config{}, err - } - - return config, nil -} - -// This should be a popup for the user -func get_accesstoken() (*http.Client, OauthToken, error) { - ctx := context.Background() - config, err := getOfficeAppInfo() - if err != nil { - return nil, OauthToken{}, err - } - - conf := &oauth2.Config{ - ClientID: config.ClientID, - ClientSecret: config.ClientSecret, - Scopes: []string{ - "Mail.Read", - "User.Read", - "https://outlook.office.com/mail.read", - }, - RedirectURL: "https://localhost:8000", - Endpoint: oauth2.Endpoint{ - AuthURL: config.AuthUrl, - TokenURL: config.TokenUrl, - }, - } - //"Mail.Read.Shared", - - //url := conf.AuthCodeURL("state", oauth2.SetAuthURLParam("resource", "https://outlook.office.com")) - // ADD DATA TO STATE HERE :O - url := conf.AuthCodeURL("workflow_id%3Dc2e0b50a-2957-427e-a97b-b989dc5a5408%26trigger_id%3D9e845679-5843-4959-a76c-a6d664e9df35%26username%3Drheyix.yt@gmail.com", oauth2.SetAuthURLParam("resource", "https://graph.microsoft.com")) - - fmt.Printf("Visit the URL for the auth dialog: \n%v\n\n", url) - codechannel := make(chan string) - - // Handles the server callback, listening on port 8000 - go func() { - port := ":8000" - - http.HandleFunc("/", func(response http.ResponseWriter, request *http.Request) { - tmpcode := request.URL.Query().Get("code") - if len(tmpcode) < 100 { - return - } else { - codechannel <- tmpcode - } - }) - - // FIX - might cause errors not being printed - err := http.ListenAndServeTLS(port, "integrations/server.crt", "integrations/server.key", nil) - if err != nil { - log.Printf("%s\n", err) - } - }() - - code := <-codechannel - close(codechannel) - - // https://stackoverflow.com/questions/52787420/multiple-resources-in-a-single-authorization-request - // Multi resource ^ - access_token, err := conf.Exchange(ctx, code) - //log.Printf("%#v", access_token) - if err != nil { - return nil, OauthToken{}, err - } - - //log.Printf("%#v", access_token) - outlookClient := conf.Client(ctx, access_token) - - oauthToken := OauthToken{ - AccessToken: access_token.AccessToken, - TokenType: access_token.TokenType, - RefreshToken: access_token.RefreshToken, - Expiry: access_token.Expiry, - } - - return outlookClient, oauthToken, nil -} - -type OauthToken struct { - AccessToken string `json:"AccessToken" datastore:"AccessToken,noindex"` - TokenType string `json:"TokenType" datastore:"TokenType,noindex"` - RefreshToken string `json:"RefreshToken" datastore:"RefreshToken,noindex"` - Expiry time.Time `json:"Expiry" datastore:"Expiry,noindex"` -} - -type Mailfolders struct { - OdataContext string `json:"@odata.context"` - OdataNextLink string `json:"@odata.nextLink"` - Value []struct { - ID string `json:"id"` - DisplayName string `json:"displayName"` - ParentFolderID string `json:"parentFolderId"` - ChildFolderCount int `json:"childFolderCount"` - UnreadItemCount int `json:"unreadItemCount"` - TotalItemCount int `json:"totalItemCount"` - } `json:"value"` -} - -func getFolders(client *http.Client) (Mailfolders, error) { - requestUrl := fmt.Sprintf("https://graph.microsoft.com/v1.0/users/frikky@shuffletest.onmicrosoft.com/mailfolders") - - ret, err := client.Get(requestUrl) - if err != nil { - log.Printf("FolderErr: %s", err) - return Mailfolders{}, err - } - - log.Printf("Status folders: %d", ret.StatusCode) - body, err := ioutil.ReadAll(ret.Body) - if err != nil { - log.Printf("Body: %s", err) - return Mailfolders{}, err - } - - //log.Printf("Body: %s", string(body)) - - mailfolders := Mailfolders{} - err = json.Unmarshal(body, &mailfolders) - if err != nil { - log.Printf("Unmarshal: %s", err) - return Mailfolders{}, err - } - - //fmt.Printf("%#v", mailfolders) - // FIXME - recursion for subfolders - // Recursive struct - // folderEndpoint := fmt.Sprintf("%s/%s/childfolders?$top=40", requestUrl, parentId) - for _, folder := range mailfolders.Value { - log.Println(folder.DisplayName) - } - - return mailfolders, nil -} - -// Subscribes to a mailbox based on some thingies -func makeSubscription(client *http.Client, folderIds []string) { - // FIXME - show the users folders from oauth and let them choose - - fullUrl := "https://graph.microsoft.com/v1.0/subscriptions" - //resource := fmt.Sprintf("https://outlook.office.com/api/v2.0/me/mailfolders('inbox')/messages") - resource := fmt.Sprintf("me/mailfolders('inbox')/messages") - sub := Subscription{ - ChangeType: "created", - NotificationURL: "https://de4fc12b.ngrok.io", - ExpirationDateTime: "2019-09-22T18:23:45.9356913Z", - ClientState: "This is a test", - Resource: resource, - } - - data, err := json.Marshal(sub) - if err != nil { - log.Printf("Marshal: %s", err) - return - } - - log.Printf(string(data)) - - req, err := http.NewRequest( - "POST", - fullUrl, - bytes.NewBuffer(data), - ) - req.Header.Add("Content-Type", "application/json") - - res, err := client.Do(req) - if err != nil { - log.Printf("Client: %s", err) - return - } - - log.Printf("Status: %d", res.StatusCode) - body, err := ioutil.ReadAll(res.Body) - if err != nil { - log.Printf("Body: %s", err) - return - } - - fmt.Println(string(body)) - log.Println("Shoooould be set up :)") - -} - -func getOutlookClient(code string, accessToken OauthToken, redirectUri string) (*http.Client, *oauth2.Token, error) { - ctx := context.Background() - - conf := &oauth2.Config{ - ClientID: "70e37005-c954-4290-b573-d4b94e484336", - ClientSecret: ".eNw/A[kQFB5zL.agvRputdEJENeJ392", - Scopes: []string{ - "Mail.Read", - "User.Read", - "https://outlook.office.com/mail.read", - }, - RedirectURL: redirectUri, - Endpoint: oauth2.Endpoint{ - AuthURL: "https://login.microsoftonline.com/common/oauth2/authorize", - TokenURL: "https://login.microsoftonline.com/common/oauth2/token", - }, - } - - if len(code) > 0 { - access_token, err := conf.Exchange(ctx, code) - if err != nil { - log.Printf("Access_token issue: %s", err) - return &http.Client{}, access_token, err - } - - client := conf.Client(ctx, access_token) - return client, access_token, nil - } else { - // Manually recreate the oauthtoken - access_token := &oauth2.Token{ - AccessToken: accessToken.AccessToken, - TokenType: accessToken.TokenType, - RefreshToken: accessToken.RefreshToken, - Expiry: accessToken.Expiry, - } - - client := conf.Client(ctx, access_token) - return client, access_token, nil - } -} - -func main() { - graphclient, oauthToken, err := get_accesstoken() - if err != nil { - log.Printf("Oauth setup: %s", err) - return - } - - // FIXME - make this possible for alternative users (shared) - folders, err := getFolders(graphclient) - if err != nil { - log.Printf("Folder get error: %s", err) - return - } - _ = folders - - folderIds := []string{"inbox"} - //log.Println(folders) - //log.Printf("%#v", oauthToken) - // Use oauthToken to generate data for outlook - outlookclient, _, err := getOutlookClient("", oauthToken, "https://localhost:8000") - makeSubscription(outlookclient, folderIds) -}