Skip to content

Commit

Permalink
Initial implementation: supports connect and viewcal, untested (#1)
Browse files Browse the repository at this point in the history
* command  + http framework

* Got a 404 on the hardcoded Mattermost Org - no Outlook

* `/msoffice viewcal` works on a personal account

- added OAuth2 credentials a config values

* PR feedback
  • Loading branch information
levb authored Nov 13, 2019
1 parent f90efe2 commit df0d1fd
Show file tree
Hide file tree
Showing 41 changed files with 1,799 additions and 218 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ apply:

## Runs govet and gofmt against all packages.
.PHONY: check-style
check-style: webapp/.npminstall gofmt govet golint
check-style: webapp/.npminstall gofmt govet
@echo Checking for style guide compliance

ifneq ($(HAS_WEBAPP),)
Expand Down
23 changes: 7 additions & 16 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,22 +1,13 @@
module github.com/mattermost/mattermost-plugin-starter-template
module github.com/mattermost/mattermost-plugin-msoffice

go 1.12
go 1.13

require (
github.com/blang/semver v3.6.1+incompatible // indirect
github.com/go-ldap/ldap v3.0.3+incompatible // indirect
github.com/hashicorp/go-hclog v0.9.2 // indirect
github.com/hashicorp/go-plugin v1.0.1 // indirect
github.com/lib/pq v1.1.1 // indirect
github.com/mattermost/go-i18n v1.11.0 // indirect
github.com/mattermost/mattermost-server v5.12.0+incompatible
github.com/pelletier/go-toml v1.4.0 // indirect
github.com/gorilla/mux v1.7.3
github.com/jkrecek/msgraph-go v0.0.0-20190328140430-9f7466d8cb1f
github.com/mattermost/mattermost-server v0.0.0-20190927121038-340287890a78
github.com/pkg/errors v0.8.1
github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad // indirect
github.com/stretchr/testify v1.3.0
)

replace (
git.apache.org/thrift.git => github.com/apache/thrift v0.0.0-20180902110319-2566ecd5d999
// Workaround for https://github.com/golang/go/issues/30831 and fallout.
github.com/golang/lint => github.com/golang/lint v0.0.0-20190227174305-8f45f776aaf1
golang.org/x/oauth2 v0.0.0-20190319182350-c85d3e98c914
)
171 changes: 119 additions & 52 deletions go.sum

Large diffs are not rendered by default.

41 changes: 34 additions & 7 deletions plugin.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"id": "com.mattermost.plugin-starter-template",
"name": "Plugin Starter Template",
"description": "This plugin serves as a starting point for writing a Mattermost plugin.",
"id": "com.mattermost.msoffice",
"name": "TODO:name",
"description": "TODO: description.",
"version": "0.1.0",
"min_server_version": "5.12.0",
"min_server_version": "5.16.0",
"server": {
"executables": {
"linux-amd64": "server/dist/plugin-linux-amd64",
Expand All @@ -16,7 +16,34 @@
},
"settings_schema": {
"header": "",
"footer": "",
"settings": []
"settings": [
{
"key": "AdminUserIDs",
"display_name": "Admin User IDs:",
"type": "text",
"help_text": "List of users authorized to administer the plugin in addition to the System Admins. Must be a comma-separated list of user IDs.\n \nUser IDs can be found by navigating to **System Console** > **User Management**. After clicking into a user's name, their ID is on the right-hand side of the blue header."
},
{
"key": "OAuth2Authority",
"display_name": "Microsoft Office Authority (\"common\", or application tenant ID)",
"type": "text",
"help_text": "\"common\", or application tenant ID.",
"default": "common"
},
{
"key": "OAuth2ClientId",
"display_name": "Microsoft Office Client ID",
"type": "text",
"help_text": "Microsoft Office Client ID.",
"default": ""
},
{
"key": "OAuth2ClientSecret",
"display_name": "Microsoft Office Client Secret",
"type": "text",
"help_text": "Microsoft Office Client Secret.",
"default": ""
}
]
}
}
}
126 changes: 126 additions & 0 deletions server/command/command.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
// Copyright (c) 2019-present Mattermost, Inc. All Rights Reserved.
// See License for license information.

package command

import (
"fmt"
"strings"

"github.com/pkg/errors"

"github.com/mattermost/mattermost-server/model"
"github.com/mattermost/mattermost-server/plugin"

"github.com/mattermost/mattermost-plugin-msoffice/server/config"
"github.com/mattermost/mattermost-plugin-msoffice/server/user"
"github.com/mattermost/mattermost-plugin-msoffice/server/utils"
)

// Handler handles commands
type Handler struct {
Config *config.Config
UserStore user.Store
API plugin.API
BotPoster utils.BotPoster
IsAuthorizedAdmin func(userId string) (bool, error)

Context *plugin.Context
Args *model.CommandArgs
ChannelId string
MattermostUserId string
User *user.User
}

func getHelp() string {
help := `
TODO: help text.
`
return codeBlock(fmt.Sprintf(
help,
))
}

// Register is a function that allows the runner to register commands with the mattermost server.
type RegisterFunc func(*model.Command) error

// Init should be called by the plugin to register all necessary commands
func Register(registerFunc RegisterFunc) {
_ = registerFunc(&model.Command{
Trigger: config.CommandTrigger,
DisplayName: "TODO display name",
Description: "TODO description",
AutoComplete: true,
AutoCompleteDesc: "TODO autocomplete desc",
AutoCompleteHint: "TODO autocomplete hint",
})
}

// Execute should be called by the plugin when a command invocation is received from the Mattermost server.
func (h *Handler) Handle() (string, error) {
cmd, parameters, err := h.isValid()
if err != nil {
return "", err
}

h.MattermostUserId = h.Args.UserId
auth, err := h.IsAuthorizedAdmin(h.MattermostUserId)
if err != nil {
return "", errors.WithMessage(err, "Failed to get authorization. Please contact your system administrator.\nFailure")
}
if !auth {
return "", errors.New("You must be authorized to use the plugin. Please contact your system administrator.")
}

handler := h.help
switch cmd {
case "info":
handler = h.info
case "connect":
handler = h.connect
case "viewcal":
handler = h.viewCalendar
}
out, err := handler(parameters...)
if err != nil {
return "", errors.WithMessagef(err, "Command /%s %s failed", config.CommandTrigger, cmd)
}

return out, nil
}

func (h *Handler) loadRemoteUser() (*user.User, error) {
user := user.User{}
err := h.UserStore.LoadRemoteUser(h.MattermostUserId, &user)
if err != nil {
return nil, err
}
return &user, nil
}

func (h *Handler) isValid() (subcommand string, parameters []string, err error) {
if h.Context == nil || h.Args == nil || h.Config.MattermostSiteURL == "" {
return "", nil, errors.New("Invalid arguments to command.Handler")
}

split := strings.Fields(h.Args.Command)
command := split[0]
if command != "/"+config.CommandTrigger {
return "", nil, errors.Errorf("%q is not a supported command. Please contact your system administrator.", command)
}

parameters = []string{}
subcommand = ""
if len(split) > 1 {
subcommand = split[1]
}
if len(split) > 2 {
parameters = split[2:]
}

return subcommand, parameters, nil
}

func codeBlock(in string) string {
return fmt.Sprintf("```\n%s\n```", in)
}
17 changes: 17 additions & 0 deletions server/command/connect.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright (c) 2019-present Mattermost, Inc. All Rights Reserved.
// See License for license information.

package command

import (
"fmt"

"github.com/mattermost/mattermost-plugin-msoffice/server/config"
)

func (r *Handler) connect(parameters ...string) (string, error) {
out := fmt.Sprintf("[Click here to link your %s account.](%s/oauth2/connect)",
config.ApplicationName,
r.Config.PluginURL)
return out, nil
}
23 changes: 23 additions & 0 deletions server/command/help.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright (c) 2019-present Mattermost, Inc. All Rights Reserved.
// See License for license information.

package command

import (
"fmt"

"github.com/mattermost/mattermost-plugin-msoffice/server/config"
)

func (r *Handler) help(parameters ...string) (string, error) {
resp := fmt.Sprintf("Mattermost Microsoft Office plugin version: %s, "+
"[%s](https://github.com/mattermost/%s/commit/%s), built %s\n",
r.Config.PluginVersion,
r.Config.BuildHashShort,
config.Repository,
r.Config.BuildHash,
r.Config.BuildDate)
resp += "\n"
resp += "TODO help"
return resp, nil
}
21 changes: 21 additions & 0 deletions server/command/info.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright (c) 2019-present Mattermost, Inc. All Rights Reserved.
// See License for license information.

package command

import (
"fmt"

"github.com/mattermost/mattermost-plugin-msoffice/server/config"
)

func (r *Handler) info(parameters ...string) (string, error) {
resp := fmt.Sprintf("Mattermost Microsoft Office plugin version: %s, "+
"[%s](https://github.com/mattermost/%s/commit/%s), built %s\n",
r.Config.PluginVersion,
r.Config.BuildHashShort,
config.Repository,
r.Config.BuildHash,
r.Config.BuildDate)
return resp, nil
}
27 changes: 27 additions & 0 deletions server/command/view_calendar.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright (c) 2019-present Mattermost, Inc. All Rights Reserved.
// See License for license information.

package command

import (
"encoding/json"

"github.com/mattermost/mattermost-plugin-msoffice/server/msgraph"
)

func (h *Handler) viewCalendar(parameters ...string) (string, error) {
user, err := h.loadRemoteUser()
if err != nil {
return "", err
}

msgraphClient := msgraph.NewClient(h.Config, user.OAuth2Token)
cals, err := msgraphClient.GetUserCalendar("")
if err != nil {
return "", err
}

bb, _ := json.MarshalIndent(cals, "", " ")
resp := "<><>" + string(bb)
return resp, nil
}
36 changes: 36 additions & 0 deletions server/config/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package config

// StoredConfig represents the data stored in and managed with the Mattermost
// config.
type StoredConfig struct {
OAuth2Authority string
OAuth2ClientId string
OAuth2ClientSecret string

// Bot username
BotUserName string `json:"username"`

// AdminUserIDs contains a comma-separated list of user IDs that are allowed
// to administer plugin functions, even if not Mattermost sysadmins.
AdminUserIDs string
}

// Config represents the the metadata handed to all request runners (command,
// http).
type Config struct {
StoredConfig

BuildHash string
BuildHashShort string
BuildDate string

MattermostSiteHostname string
MattermostSiteURL string
PluginId string
PluginURL string
PluginURLPath string
PluginVersion string

BotIconURL string
BotUserId string
}
11 changes: 11 additions & 0 deletions server/config/const.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Copyright (c) 2019-present Mattermost, Inc. All Rights Reserved.
// See License for license information.

package config

const (
ApplicationName = "Microsoft Office"
Repository = "mattermost-plugin-msoffice"
CommandTrigger = "msoffice"
GraphURL = "https://graph.microsoft.com"
)
Loading

0 comments on commit df0d1fd

Please sign in to comment.