Skip to content
Open
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
42 changes: 33 additions & 9 deletions plugin/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,20 @@ func (m *Manager) initializeSingleUserPlugin(userCtx compat.UserContext, p compa
m.instances[pluginConf.ID] = instance

if compat.HasSupport(instance, compat.Messenger) {
if pluginConf.ApplicationID == 0 {
// The Messenger capability was added after this plugin was first
// initialized for the user, so no internal application exists yet.
// Create one now, otherwise messages would be stored with
// application_id = 0 and become orphaned (not shown, not deletable).
app, err := m.createInternalApplication(info, userID)
if err != nil {
return err
}
pluginConf.ApplicationID = app.ID
if err := m.db.UpdatePluginConf(pluginConf); err != nil {
return err
}
}
instance.SetMessageHandler(redirectToChannel{
ApplicationID: pluginConf.ApplicationID,
UserID: pluginConf.UserID,
Expand Down Expand Up @@ -399,15 +413,8 @@ func (m *Manager) createPluginConf(instance compat.PluginInstance, info compat.I
pluginConf.Config, _ = yaml.Marshal(instance.DefaultConfig())
}
if compat.HasSupport(instance, compat.Messenger) {
tokenPublic, _ := auth.GenerateApplicationToken()
app := &model.Application{
Token: tokenPublic,
Name: info.String(),
UserID: userID,
Internal: true,
Description: fmt.Sprintf("auto generated application for %s", info.ModulePath),
}
if err := m.db.CreateApplication(app); err != nil {
app, err := m.createInternalApplication(info, userID)
if err != nil {
return nil, err
}
pluginConf.ApplicationID = app.ID
Expand All @@ -417,3 +424,20 @@ func (m *Manager) createPluginConf(instance compat.PluginInstance, info compat.I
}
return pluginConf, nil
}

// createInternalApplication creates the auto generated internal application a
// Messenger plugin uses to publish its messages.
func (m *Manager) createInternalApplication(info compat.Info, userID uint) (*model.Application, error) {
tokenPublic, _ := auth.GenerateApplicationToken()
app := &model.Application{
Token: tokenPublic,
Name: info.String(),
UserID: userID,
Internal: true,
Description: fmt.Sprintf("auto generated application for %s", info.ModulePath),
}
if err := m.db.CreateApplication(app); err != nil {
return nil, err
}
return app, nil
}
34 changes: 34 additions & 0 deletions plugin/manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,40 @@ func TestNewManager_InternalApplicationManagement(t *testing.T) {
}
}

func TestNewManager_MessengerAddedAfterInit_createsApplication(t *testing.T) {
db := testdb.NewDBWithDefaultUser(t)

// Simulate a plugin conf that was created on a previous startup when the
// plugin did not yet implement the Messenger interface: it has no
// associated internal application (ApplicationID == 0).
assert.NoError(t, db.CreatePluginConf(&model.PluginConf{
UserID: 1,
ModulePath: mock.ModulePath,
Enabled: true,
Token: auth.GeneratePluginToken(),
}))

manager, err := NewManager(db, "", nil, nil)
assert.Nil(t, err)
assert.Nil(t, manager.LoadPlugin(new(mock.Plugin)))
// The mock plugin supports Messenger, so re-initializing must back-fill the
// missing internal application instead of leaving ApplicationID at 0.
assert.Nil(t, manager.InitializeForUserID(1))

conf, err := db.GetPluginConfByUserAndPath(1, mock.ModulePath)
assert.NoError(t, err)
if assert.NotNil(t, conf) {
assert.NotZero(t, conf.ApplicationID, "an internal application should have been created for the messenger plugin")

app, err := db.GetApplicationByID(conf.ApplicationID)
assert.NoError(t, err)
if assert.NotNil(t, app) {
assert.True(t, app.Internal)
assert.Equal(t, uint(1), app.UserID)
}
}
}

func TestPluginFileLoadError(t *testing.T) {
err := pluginFileLoadError{Filename: "test.so", UnderlyingError: errors.New("test error")}
assert.Error(t, err)
Expand Down
Loading