Skip to content

Commit

Permalink
Added tee log to admins as bot messages (#9)
Browse files Browse the repository at this point in the history
* Added tee log to admins as bot messages

Cleanup

* Merged ./cicrleci from more current plugins

* PR feedback
  • Loading branch information
levb authored Dec 9, 2019
1 parent 181ac45 commit 80abaaa
Show file tree
Hide file tree
Showing 29 changed files with 509 additions and 215 deletions.
67 changes: 46 additions & 21 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -1,27 +1,52 @@
version: 2.1
executors:
default:
docker:
- image: circleci/golang:1.12-node

jobs:
lint:
executor:
name: default
steps:
- checkout
- run: make check-style

test:
executor:
name: default
steps:
- checkout
- run: make test
orbs:
plugin-ci: mattermost/plugin-ci@volatile

workflows:
version: 2
untagged-build:
ci:
jobs:
- lint
- test
- plugin-ci/lint:
filters:
tags:
only: /^v.*/
- plugin-ci/coverage:
filters:
tags:
only: /^v.*/
- plugin-ci/build:
filters:
tags:
only: /^v.*/
- plugin-ci/deploy-ci:
filters:
branches:
only: master
context: plugin-ci
requires:
- plugin-ci/lint
- plugin-ci/coverage
- plugin-ci/build
- plugin-ci/deploy-release:
filters:
tags:
only: /^v.*/
branches:
ignore: /.*/
context: plugin-ci
requires:
- plugin-ci/lint
- plugin-ci/coverage
- plugin-ci/build
- plugin-ci/deploy-release-github:
filters:
tags:
only: /^v.*/
branches:
ignore: /.*/
context: matterbuild-github-token
requires:
- plugin-ci/lint
- plugin-ci/coverage
- plugin-ci/build
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ ifneq ($(HAS_SERVER),)
mockgen -destination server/remote/mock_remote/mock_remote.go github.com/mattermost/mattermost-plugin-msoffice/server/remote Remote
mockgen -destination server/remote/mock_remote/mock_client.go github.com/mattermost/mattermost-plugin-msoffice/server/remote Client
mockgen -destination server/utils/bot/mock_bot/mock_poster.go github.com/mattermost/mattermost-plugin-msoffice/server/utils/bot Poster
mockgen -destination server/utils/bot/mock_bot/mock_admin.go github.com/mattermost/mattermost-plugin-msoffice/server/utils/bot Admin
mockgen -destination server/store/mock_store/mock_oauth2_store.go github.com/mattermost/mattermost-plugin-msoffice/server/store OAuth2StateStore
mockgen -destination server/store/mock_store/mock_subscription_store.go github.com/mattermost/mattermost-plugin-msoffice/server/store SubscriptionStore
mockgen -destination server/store/mock_store/mock_user_store.go github.com/mattermost/mattermost-plugin-msoffice/server/store UserStore
Expand Down
36 changes: 36 additions & 0 deletions plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,42 @@
"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": "AdminLogLevel",
"display_name": "Copy plugin logs to admins, as bot messages",
"type": "dropdown",
"help_text": "Select the log level",
"default": "none",
"options": [
{
"display_name": "None",
"value": "none"
},
{
"display_name": "Debug",
"value": "debug"
},
{
"display_name": "Info",
"value": "info"
},
{
"display_name": "Warning",
"value": "warn"
},
{
"display_name": "Error",
"value": "error"
}
]
},
{
"key": "AdminLogVerbose",
"display_name": "Display full context for each admin log message",
"type": "bool",
"help_text": "",
"default": false
},
{
"key": "OAuth2Authority",
"display_name": "Microsoft Office Authority (\"common\", or application tenant ID)",
Expand Down
3 changes: 1 addition & 2 deletions server/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
"github.com/mattermost/mattermost-plugin-msoffice/server/config"
"github.com/mattermost/mattermost-plugin-msoffice/server/remote"
"github.com/mattermost/mattermost-plugin-msoffice/server/store"
"github.com/mattermost/mattermost-plugin-msoffice/server/utils"
"github.com/mattermost/mattermost-plugin-msoffice/server/utils/bot"
)

Expand Down Expand Up @@ -57,7 +56,7 @@ type Dependencies struct {
OAuth2StateStore store.OAuth2StateStore
SubscriptionStore store.SubscriptionStore
EventStore store.EventStore
Logger utils.Logger
Logger bot.Logger
Poster bot.Poster
Remote remote.Remote
IsAuthorizedAdmin func(userId string) (bool, error)
Expand Down
4 changes: 2 additions & 2 deletions server/api/mock_api/mock_dependencies.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"github.com/mattermost/mattermost-plugin-msoffice/server/api"
"github.com/mattermost/mattermost-plugin-msoffice/server/remote/mock_remote"
"github.com/mattermost/mattermost-plugin-msoffice/server/store/mock_store"
"github.com/mattermost/mattermost-plugin-msoffice/server/utils"
"github.com/mattermost/mattermost-plugin-msoffice/server/utils/bot"
"github.com/mattermost/mattermost-plugin-msoffice/server/utils/bot/mock_bot"
)

Expand All @@ -17,7 +17,7 @@ func NewMockDependencies(ctrl *gomock.Controller) *api.Dependencies {
UserStore: mock_store.NewMockUserStore(ctrl),
OAuth2StateStore: mock_store.NewMockOAuth2StateStore(ctrl),
SubscriptionStore: mock_store.NewMockSubscriptionStore(ctrl),
Logger: utils.NilLogger,
Logger: &bot.NilLogger{},
Poster: mock_bot.NewMockPoster(ctrl),
Remote: mock_remote.NewMockRemote(ctrl),
}
Expand Down
38 changes: 22 additions & 16 deletions server/api/notification.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ import (
"github.com/mattermost/mattermost-plugin-msoffice/server/config"
"github.com/mattermost/mattermost-plugin-msoffice/server/remote"
"github.com/mattermost/mattermost-plugin-msoffice/server/store"
"github.com/mattermost/mattermost-plugin-msoffice/server/utils/bot"
"github.com/mattermost/mattermost-plugin-msoffice/server/utils/fields"
"github.com/mattermost/mattermost-plugin-msoffice/server/utils/kvstore"
)

const maxQueueSize = 1024
Expand Down Expand Up @@ -88,8 +88,7 @@ func (h *notificationHandler) work() {
select {
case n := <-h.incoming:
if h.queueSize >= maxQueueSize {
h.Logger.LogError(
fmt.Sprintf("Notification queue full (%v), dropped notification", h.queueSize))
h.Logger.Errorf("webhook notification: queue full (`%v`), dropped notification", h.queueSize)
continue
}
h.queueSize++
Expand All @@ -99,8 +98,9 @@ func (h *notificationHandler) work() {
h.queueSize--
err := h.processNotification(n)
if err != nil {
h.Logger.LogInfo("Failed to process notification: "+err.Error(),
"SubsriptionID", n.SubscriptionID)
h.Logger.With(bot.LogContext{
"subscriptionID": n.SubscriptionID,
}).Infof("webhook notification: failed: `%v`.", err)
}

case apiConfig := <-h.configChan:
Expand Down Expand Up @@ -152,9 +152,10 @@ func (h *notificationHandler) processNotification(n *remote.Notification) error
if err != nil {
return err
}
h.Logger.LogDebug("Renewed user subscription",
"MattermostUserID", creator.MattermostUserID,
"SubsriptionID", n.SubscriptionID)
h.Logger.With(bot.LogContext{
"MattermostUserID": creator.MattermostUserID,
"SubsriptionID": n.SubscriptionID,
}).Debugf("webhook notification: renewed user subscription.")
}

if n.IsBare {
Expand All @@ -166,24 +167,27 @@ func (h *notificationHandler) processNotification(n *remote.Notification) error

var sa *model.SlackAttachment
prior, err := h.EventStore.LoadUserEvent(creator.MattermostUserID, n.Event.ID)
if err != nil && err != kvstore.ErrNotFound {
if err != nil && err != store.ErrNotFound {
return err
}
if prior != nil {
var changed bool
changed, sa = h.updatedEventSlackAttachment(n, prior.Remote)
if !changed {
h.Logger.LogDebug("No changes detected in event",
"MattermostUserID", creator.MattermostUserID,
"SubsriptionID", n.SubscriptionID)
h.Logger.With(bot.LogContext{
"MattermostUserID": creator.MattermostUserID,
"SubsriptionID": n.SubscriptionID,
"ChangeType": n.ChangeType,
"EventID": n.Event.ID,
}).Debugf("webhook notification: no changes detected in event.")
return nil
}
} else {
sa = h.newEventSlackAttachment(n)
prior = &store.Event{}
}

err = h.Poster.PostDirectAttachments(creator.MattermostUserID, sa)
err = h.Poster.DMWithAttachments(creator.MattermostUserID, sa)
if err != nil {
return err
}
Expand All @@ -194,9 +198,11 @@ func (h *notificationHandler) processNotification(n *remote.Notification) error
return err
}

h.Logger.LogDebug("Processed notification: "+sa.Title,
"MattermostUserID", creator.MattermostUserID,
"SubsriptionID", n.SubscriptionID)
h.Logger.With(bot.LogContext{
"MattermostUserID": creator.MattermostUserID,
"SubsriptionID": n.SubscriptionID,
}).Debugf("Notified: %s.", sa.Title)

return nil
}

Expand Down
10 changes: 6 additions & 4 deletions server/api/oauth2.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ import (
"github.com/mattermost/mattermost-plugin-msoffice/server/store"
)

const WelcomeMessage = `### Welcome to the Microsoft Office plugin!
Here is some info to prove we got you logged in
- Name: %s
`

func (api *api) InitOAuth2(userID string) (url string, err error) {
conf := api.Remote.NewOAuth2Config()
state := fmt.Sprintf("%v_%v", model.NewId()[0:15], userID)
Expand Down Expand Up @@ -64,10 +69,7 @@ func (api *api) CompleteOAuth2(authedUserID, code, state string) error {
return err
}

message := fmt.Sprintf("### Welcome to the Microsoft Office plugin!\n"+
"Here is some info to prove we got you logged in\n"+
"Name: %s \n", me.DisplayName)
api.Poster.PostDirectf(mattermostUserID, message)
api.Poster.DM(mattermostUserID, WelcomeMessage, me.DisplayName)

return nil
}
6 changes: 3 additions & 3 deletions server/config/config.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
package config

import "github.com/mattermost/mattermost-plugin-msoffice/server/utils/bot"

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

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

// Config represents the the metadata handed to all request runners (command,
Expand Down
25 changes: 10 additions & 15 deletions server/plugin/authorization.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,21 @@ package plugin

import (
"strings"

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

// isAuthorized returns true if the user is authorized to use the workflow plugin's admin-level APIs/commands.
func (p *Plugin) IsAuthorizedAdmin(mattermostID string) (bool, error) {
user, err := p.API.GetUser(mattermostID)
// IsAuthorizedAdmin returns true if the user is either a Mattermost sysadmin,
// or is a designated plugin administrator (see config.StoredConfig).
func (p *Plugin) IsAuthorizedAdmin(mattermostUserID string) (bool, error) {
user, err := p.API.GetUser(mattermostUserID)
if err != nil {
return false, err
}
if strings.Contains(user.Roles, "system_admin") || p.userAuthorized(mattermostID) {
if strings.Contains(user.Roles, "system_admin") {
return true, nil
}
return false, nil
}

func (p *Plugin) userAuthorized(mattermostID string) bool {
list := strings.Split(p.getConfig().AdminUserIDs, ",")
for _, u := range list {
if mattermostID == strings.TrimSpace(u) {
return true
}
}
return false
conf := p.getConfig()
bot := bot.GetBot(p.API, conf.BotUserID).WithConfig(conf.BotConfig)
return bot.IsUserAdmin(mattermostUserID), nil
}
19 changes: 7 additions & 12 deletions server/plugin/http/oauth2_complete_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package http

import (
"errors"
"fmt"
"net/http"
"net/url"
"testing"
Expand All @@ -17,7 +16,7 @@ import (
"github.com/mattermost/mattermost-plugin-msoffice/server/remote"
"github.com/mattermost/mattermost-plugin-msoffice/server/remote/msgraph"
"github.com/mattermost/mattermost-plugin-msoffice/server/store/mock_store"
"github.com/mattermost/mattermost-plugin-msoffice/server/utils"
"github.com/mattermost/mattermost-plugin-msoffice/server/utils/bot"
"github.com/mattermost/mattermost-plugin-msoffice/server/utils/bot/mock_bot"
)

Expand Down Expand Up @@ -121,9 +120,11 @@ func TestOAuth2Complete(t *testing.T) {

us.EXPECT().StoreUser(gomock.Any()).Return(nil).Times(1)
ss.EXPECT().VerifyOAuth2State(gomock.Eq("[email protected]")).Return(nil).Times(1)
poster.EXPECT().PostDirectf(
gomock.Eq("[email protected]"), gomock.Eq(getBotPosterMessage("displayName-value"))).
Return(nil).Times(1)
poster.EXPECT().DM(
gomock.Eq("[email protected]"),
gomock.Eq(api.WelcomeMessage),
gomock.Eq("displayName-value"),
).Return(nil).Times(1)
},
expectedHTTPCode: http.StatusOK,
expectedHTTPResponse: `
Expand Down Expand Up @@ -160,7 +161,7 @@ func TestOAuth2Complete(t *testing.T) {
}

dependencies := mock_api.NewMockDependencies(ctrl)
dependencies.Remote = remote.Makers[msgraph.Kind](conf, utils.NilLogger)
dependencies.Remote = remote.Makers[msgraph.Kind](conf, &bot.NilLogger{})
if tc.setup != nil {
tc.setup(dependencies)
}
Expand Down Expand Up @@ -260,12 +261,6 @@ func statusOKGraphAPIResponder() {
httpmock.RegisterResponder("GET", meRequestURL, meResponder)
}

func getBotPosterMessage(displayName string) string {
return fmt.Sprintf("### Welcome to the Microsoft Office plugin!\n"+
"Here is some info to prove we got you logged in\n"+
"Name: %s \n", displayName)
}

func newHTTPRequest(apiconf api.Config, mattermostUserID, rawQuery string) *http.Request {
r := &http.Request{
Header: make(http.Header),
Expand Down
Loading

0 comments on commit 80abaaa

Please sign in to comment.