Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[GH-971] Support Jira migration to Oauth #995

Merged
merged 8 commits into from
Nov 6, 2023
8 changes: 5 additions & 3 deletions server/instance_cloud_oauth.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,12 +98,14 @@ func (ci *cloudOAuthInstance) GetClient(connection *Connection) (Client, error)
func (ci *cloudOAuthInstance) getClientForConnection(connection *Connection) (*jira.Client, *http.Client, error) {
oauth2Conf := ci.GetOAuthConfig()
ctx := context.Background()
tokenSource := oauth2Conf.TokenSource(ctx, connection.OAuth2Token)
if ci.JWTInstance != nil && tokenSource == nil {
ci.Plugin.API.LogDebug("Returning a JWT token client in case the stored JWT instance is not nil and the user's oauth token is nil")

// Checking if this user's connection is for a JWT instance
if ci.JWTInstance != nil && connection.OAuth2Token == nil {
ci.Plugin.API.LogDebug("Returning a JWT token client since the stored JWT instance is not nil and the user's oauth token is nil")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you thinking we should remove log statements like this in a following release?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mickmister Yes, we will remove these in a later release. These are just to check if the code executed as we expected it to.

return ci.JWTInstance.getClientForConnection(connection)
}

tokenSource := oauth2Conf.TokenSource(ctx, connection.OAuth2Token)
client := oauth2.NewClient(ctx, tokenSource)

// Get a new token, if Access Token has expired
Expand Down
59 changes: 36 additions & 23 deletions server/instances.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,44 +141,57 @@ func (p *instancesArray) Resize(n int) {
*p = make(instancesArray, n)
}

func (p *Plugin) InstallInstance(instance Instance) error {
func (p *Plugin) InstallInstance(newInstance Instance) error {
var updated *Instances
err := UpdateInstances(p.instanceStore,
func(instances *Instances) error {
if !p.enterpriseChecker.HasEnterpriseFeatures() {
if instances != nil && len(instances.IDs()) > 0 && !instances.checkIfExists(instance.GetID()) {
if instances != nil && len(instances.IDs()) > 0 && !instances.checkIfExists(newInstance.GetID()) {
return errors.Errorf(licenseErrorString)
}
}

if instance.Common().Type == CloudOAuthInstanceType && len(instances.IDs()) > 0 && instances.checkIfExists(instance.GetID()) {
p.API.LogDebug("Getting the stored JWT instance data to store it inside the OAuth instance data.")
jwtInstance, err := p.instanceStore.LoadInstance(instance.GetID())
if err != nil {
p.API.LogError("Error occurred while fetching the instance", "ID", instance.GetID(), "Error", err.Error())
return err
}

// Storing the JWT instance data inside the OAuth instance data. We will use this to use the stored JWT token in case the user has not connected to OAuth yet.
p.API.LogDebug("Instance type stored in KV store", "ID", jwtInstance.GetID(), "Type", jwtInstance.Common().Type)
if jwtInstance.Common().Type == CloudInstanceType {
instance.(*cloudOAuthInstance).JWTInstance = jwtInstance.(*cloudInstance)
} else if jwtInstance.Common().Type == CloudOAuthInstanceType {
instance.(*cloudOAuthInstance).JWTInstance = jwtInstance.(*cloudOAuthInstance).JWTInstance
}

if instance.(*cloudOAuthInstance).JWTInstance != nil {
p.API.LogDebug("JWT instance is successfully stored inside cloud OAuth instance data.", "JWTInstance", instance.(*cloudOAuthInstance).JWTInstance)
if newInstance.Common().Type == CloudOAuthInstanceType && len(instances.IDs()) > 0 && instances.checkIfExists(newInstance.GetID()) {
oAuthInstance, ok := newInstance.(*cloudOAuthInstance)
if !ok {
p.API.LogError("Instance type is `cloud-oauth` but failed to assert instance.(*cloudOAuthInstance).", "ID", newInstance.GetID())
} else {
p.API.LogDebug("Failed to store JWT instance inside cloud OAuth instance data or there was no JWT instance installed previously.", "JWTInstance", instance.(*cloudOAuthInstance).JWTInstance)
p.API.LogDebug("Getting the stored JWT instance data to store it inside the OAuth instance data.")
previousInstance, err := p.instanceStore.LoadInstance(newInstance.GetID())
if err != nil {
p.API.LogError("Error occurred while fetching the instance", "ID", newInstance.GetID(), "Error", err.Error())
return err
}

// Storing the JWT instance data inside the OAuth instance data. We will use this to use the stored JWT token in case the user has not connected to OAuth yet.
p.API.LogDebug("Instance type stored in KV store", "ID", previousInstance.GetID(), "Type", previousInstance.Common().Type)
if previousInstance.Common().Type == CloudInstanceType {
ci, ok := previousInstance.(*cloudInstance)
if !ok {
p.API.LogError("Instance type is `cloud` but failed to assert instance.(*cloudInstance).", "ID", newInstance.GetID())
}
oAuthInstance.JWTInstance = ci
} else if previousInstance.Common().Type == CloudOAuthInstanceType {
ci, ok := previousInstance.(*cloudOAuthInstance)
if !ok {
p.API.LogError("Instance type is `cloud-oauth` but failed to assert instance.(*cloudOAuthInstance).", "ID", newInstance.GetID())
}
oAuthInstance.JWTInstance = ci.JWTInstance
raghavaggarwal2308 marked this conversation as resolved.
Show resolved Hide resolved
}

if oAuthInstance.JWTInstance != nil {
p.API.LogDebug("JWT instance is successfully stored inside cloud OAuth instance data.", "JWTInstance", oAuthInstance.JWTInstance)
} else {
p.API.LogDebug("No JWT instance inside cloud OAuth instance data.", "JWTInstance", oAuthInstance.JWTInstance)
}
}
}

err := p.instanceStore.StoreInstance(instance)
err := p.instanceStore.StoreInstance(newInstance)
if err != nil {
return err
}
instances.Set(instance.Common())
instances.Set(newInstance.Common())
updated = instances
return nil
})
Expand Down
13 changes: 12 additions & 1 deletion server/webhook_jira.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,20 @@ func (jwh *JiraWebhook) expandIssue(p *Plugin, instanceID types.ID) error {
}

jwh.Issue = *issue
} else if _, ok := instance.(*cloudOAuthInstance); ok {
} else if instance, ok := instance.(*cloudOAuthInstance); ok {
mmUserID, err := p.userStore.LoadMattermostUserID(instanceID, jwh.Comment.Author.AccountID)
if err != nil {
if instance.JWTInstance != nil {
raghavaggarwal2308 marked this conversation as resolved.
Show resolved Hide resolved
var issue *jira.Issue
issue, err = p.getIssueDataForCloudWebhook(instance.JWTInstance, jwh.Issue.ID)
if err != nil {
return err
}

jwh.Issue = *issue
return nil
}

return errors.Wrap(err, "Cannot create subscription posts for this comment as the Jira comment author is not connected to Mattermost.")
}

Expand Down
Loading