From d82036addacfc9b2bc12dc1da77d285288eb8830 Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Wed, 10 Aug 2016 10:46:29 +0100 Subject: [PATCH 1/6] Parse messy JIRA URLs into a canonicalised format --- README.md | 39 +++++++ .../matrix-org/go-neb/realms/jira/jira.go | 23 +++- .../go-neb/realms/jira/urls/urls.go | 107 ++++++++++++++++++ .../go-neb/realms/jira/urls/urls_test.go | 45 ++++++++ 4 files changed, 211 insertions(+), 3 deletions(-) create mode 100644 src/github.com/matrix-org/go-neb/realms/jira/urls/urls.go create mode 100644 src/github.com/matrix-org/go-neb/realms/jira/urls/urls_test.go diff --git a/README.md b/README.md index 64d788d..80dde8f 100644 --- a/README.md +++ b/README.md @@ -145,6 +145,45 @@ curl -X POST localhost:4050/admin/configureService --data-binary '{ This request will make `BotUserID` join the `Rooms` specified and create webhooks for the `owner/repo` projects given. + +## Starting a JIRA Service + +### Register a JIRA realm + +Generate an RSA private key: (JIRA does not support key sizes >2048 bits) + +```bash +openssl genrsa -out privkey.pem 2048 +``` + + + +``` +curl -X POST localhost:4050/admin/configureAuthRealm --data-binary '{ + "ID": "jirarealm", + "Type": "jira", + "Config": { + "ConsumerName": "goneb", + "ConsumerKey": "goneb", + "ConsumerSecret": "random_long_string", + "PrivateKeyPEM": "-----BEGIN RSA PRIVATE KEY-----\r\nMIIEowIBAAKCAQEA39UhbOvQHEkBP9fGnhU+eSObTWBDGWygVYzbcONOlqEOTJUN\r\n8gmnellWqJO45S4jB1vLLnuXiHqEWnmaShIvbUem3QnDDqghu0gfqXHMlQr5R8ZP\r\norTt1F2idWy1wk5rVXeLKSG7uriYhDVOVS69WuefoW5v55b5YZV283v2jROjxHuj\r\ngAsJA7k6tvpYiSXApUl6YHmECfBoiwG9bwItkHwhZ\/fG9i4H8\/aOyr3WlaWbVeKX\r\n+m38lmYZvzQFRAk5ab1vzCGz4cyc\r\nTk2qmZpcjHRd1ijcOkgC23KF8lHWF5Zx0tySR+DWL1JeGm8NJxKMRJZuE8MIkJYF\r\nryE7kjspNItk6npkA3\/A4PWwElhddI4JpiuK+29mMNipRcYYy9e0vH\/igejv7ayd\r\nPLCRMQKBgBDSNWlZT0nNd2DXVqTW9p+MG72VKhDgmEwFB1acOw0lpu1XE8R1wmwG\r\nZRl\/xzri3LOW2Gpc77xu6fs3NIkzQw3v1ifYhX3OrVsCIRBbDjPQI3yYjkhGx24s\r\nVhhZ5S\/TkGk3Kw59bDC6KGqAuQAwX9req2l1NiuNaPU9rE7tf6Bk\r\n-----END RSA PRIVATE KEY-----" + } +}' +``` + +Returns: + + + +### Make a request for JIRA Auth + +TODO + +### Create a JIRA bot + +TODO + + # Developing on go-neb. There's a bunch more tools this project uses when developing in order to do diff --git a/src/github.com/matrix-org/go-neb/realms/jira/jira.go b/src/github.com/matrix-org/go-neb/realms/jira/jira.go index ca0f892..3b83708 100644 --- a/src/github.com/matrix-org/go-neb/realms/jira/jira.go +++ b/src/github.com/matrix-org/go-neb/realms/jira/jira.go @@ -6,7 +6,7 @@ import ( "encoding/json" "encoding/pem" "errors" - log "github.com/Sirupsen/logrus" + "github.com/matrix-org/go-neb/realms/jira/urls" "github.com/matrix-org/go-neb/types" "net/http" ) @@ -34,14 +34,27 @@ func (r *jiraRealm) Register() error { if r.ConsumerName == "" || r.ConsumerKey == "" || r.ConsumerSecret == "" || r.PrivateKeyPEM == "" { return errors.New("ConsumerName, ConsumerKey, ConsumerSecret, PrivateKeyPEM must be specified.") } - log.Print("Registering..") + if r.JIRAEndpoint == "" { + return errors.New("JIRAEndpoint must be specified") + } + // Make sure the private key PEM is actually a private key. err := r.parsePrivateKey() if err != nil { return err } - // TODO: Check to see if JIRA endpoint is valid and known + // Parse the messy input URL into a canonicalised form. + ju, err := urls.ParseJIRAURL(r.JIRAEndpoint) + if err != nil { + return err + } + + // Check to see if JIRA endpoint is valid by pinging an endpoint + err = jiraClient(ju, "") + if err != nil { + return err + } return nil } @@ -100,6 +113,10 @@ func publicKeyAsPEM(pkey *rsa.PrivateKey) (string, error) { return string(pem.EncodeToMemory(&block)), nil } +func jiraClient(u urls.JIRAURL, userID string) error { + return nil +} + func init() { types.RegisterAuthRealm(func(realmID string) types.AuthRealm { return &jiraRealm{id: realmID} diff --git a/src/github.com/matrix-org/go-neb/realms/jira/urls/urls.go b/src/github.com/matrix-org/go-neb/realms/jira/urls/urls.go new file mode 100644 index 0000000..1dd1536 --- /dev/null +++ b/src/github.com/matrix-org/go-neb/realms/jira/urls/urls.go @@ -0,0 +1,107 @@ +// Package urls handles converting between various JIRA URL representations in a consistent way. There exists three main +// types of JIRA URL which Scalar cares about: +// - URL Keys => matrix.org/jira +// - Base URLs => https://matrix.org/jira/ +// - REST URLs => https://matrix.org/jira/rest/api/2/issue/12680 +// When making outbound requests to JIRA, Scalar needs to use the Base URL representation. Likewise, when Scalar +// sends Matrix messages with JIRA URLs in them, the Base URL needs to be used to form the URL. The URL Key is +// used to determine equivalence of various JIRA installations and is mainly required when searching the database. +// The REST URLs are present on incoming webhook events and are the only way to map the event to a JIRA installation. +package urls + +import ( + "errors" + "net/url" + "strings" +) + +// JIRAURL contains the parsed representation of a JIRA URL +type JIRAURL struct { + Base string // The base URL of the JIRA installation. Always has a trailing / and a protocol. + Key string // The URL key of the JIRA installation. Never has a trailing / or a protocol. + Raw string // The raw input URL, if given. Freeform. +} + +// ParseJIRAURL parses a raw input URL and returns a struct which has various JIRA URL representations. The input +// URL can be a JIRA REST URL, a speculative base JIRA URL from a client, or a URL key. The input string will be +// stored as under JIRAURL.Raw. If a URL key is given, this struct will default to https as the protocol. +func ParseJIRAURL(u string) (j JIRAURL, err error) { + if u == "" { + err = errors.New("No input JIRA URL") + return + } + j.Raw = u + // URL keys don't have a protocol, everything else does + if !strings.HasPrefix(u, "https://") && !strings.HasPrefix(u, "http://") { + // assume input is a URL key + k, e := makeURLKey(u) + if e != nil { + err = e + return + } + j.Key = k + j.Base = makeBaseURL(u) + return + } + // Attempt to parse out REST API paths. This is a horrible heuristic which mostly works. + if strings.Contains(u, "/rest/api/") { + j.Base = makeBaseURL(strings.Split(u, "/rest/api/")[0]) + } else { + // Assume it already is a base URL + j.Base = makeBaseURL(u) + } + + k, e := makeURLKey(j.Base) + if e != nil { + err = e + return + } + j.Key = k + return +} + +// SameJIRAURL returns true if the two given JIRA URLs are pointing to the same JIRA installation. +// Equivalence is determined solely by the provided URLs, by sanitising them then comparing. +func SameJIRAURL(a, b string) bool { + ja, err := ParseJIRAURL(a) + if err != nil { + return false + } + jb, err := ParseJIRAURL(b) + if err != nil { + return false + } + return ja.Key == jb.Key +} + +// makeBaseURL assumes the input is a base URL and makes sure that the string conforms to JIRA Base URL rules: +// - Must have a protocol +// - Must have a trailing slash +// Defaults to HTTPS if there is no protocol specified. +func makeBaseURL(s string) string { + if !strings.HasPrefix(s, "https://") && !strings.HasPrefix(s, "http://") { + s = "https://" + s + } + return withTrailingSlash(s) +} + +// makeURLKey assumes the input is a URL key and makes sure that the string conforms to JIRA URL Key rules: +// - Must not have a protocol +// - Must not have a trailing slash +// For example: +// https://matrix.org/jira/ => matrix.org/jira +func makeURLKey(s string) (string, error) { + u, err := url.Parse(s) + if err != nil { + return "", err + } + return u.Host + strings.TrimSuffix(u.Path, "/"), nil +} + +// withTrailingSlash makes sure the input string has a trailing slash. Will not add one if one already exists. +func withTrailingSlash(s string) string { + if strings.HasSuffix(s, "/") { + return s + } + return s + "/" +} diff --git a/src/github.com/matrix-org/go-neb/realms/jira/urls/urls_test.go b/src/github.com/matrix-org/go-neb/realms/jira/urls/urls_test.go new file mode 100644 index 0000000..288b239 --- /dev/null +++ b/src/github.com/matrix-org/go-neb/realms/jira/urls/urls_test.go @@ -0,0 +1,45 @@ +package urls + +import ( + "testing" +) + +var urltests = []struct { + in string + outKey string + outBase string + outRaw string +}{ + // valid url key as input + {"matrix.org/jira", "matrix.org/jira", "https://matrix.org/jira/", "matrix.org/jira"}, + // valid url base as input + {"https://matrix.org/jira/", "matrix.org/jira", "https://matrix.org/jira/", "https://matrix.org/jira/"}, + // valid rest url as input + {"https://matrix.org/jira/rest/api/2/issue/12680", "matrix.org/jira", "https://matrix.org/jira/", "https://matrix.org/jira/rest/api/2/issue/12680"}, + // missing trailing slash as input + {"https://matrix.org/jira", "matrix.org/jira", "https://matrix.org/jira/", "https://matrix.org/jira"}, + // missing protocol but with trailing slash + {"matrix.org/jira/", "matrix.org/jira", "https://matrix.org/jira/", "matrix.org/jira/"}, + // no jira path as base url (subdomain) + {"https://jira.matrix.org", "jira.matrix.org", "https://jira.matrix.org/", "https://jira.matrix.org"}, + // explicit http as input + {"http://matrix.org/jira", "matrix.org/jira", "http://matrix.org/jira/", "http://matrix.org/jira"}, +} + +func TestParseJIRAURL(t *testing.T) { + for _, urltest := range urltests { + jURL, err := ParseJIRAURL(urltest.in) + if err != nil { + t.Fatal(err) + } + if jURL.Key != urltest.outKey { + t.Fatalf("ParseJIRAURL(%s) => Key: Want %s got %s", urltest.in, urltest.outKey, jURL.Key) + } + if jURL.Base != urltest.outBase { + t.Fatalf("ParseJIRAURL(%s) => Base: Want %s got %s", urltest.in, urltest.outBase, jURL.Key) + } + if jURL.Raw != urltest.outRaw { + t.Fatalf("ParseJIRAURL(%s) => Raw: Want %s got %s", urltest.in, urltest.outRaw, jURL.Raw) + } + } +} From 513c9318fb6890cc25fdd4340f057f35418a41c5 Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Wed, 10 Aug 2016 11:18:24 +0100 Subject: [PATCH 2/6] Allow the creation of [un]authenticated JIRA clients --- .../matrix-org/go-neb/realms/jira/jira.go | 75 ++++++++++++++++++- 1 file changed, 72 insertions(+), 3 deletions(-) diff --git a/src/github.com/matrix-org/go-neb/realms/jira/jira.go b/src/github.com/matrix-org/go-neb/realms/jira/jira.go index 3b83708..15eb440 100644 --- a/src/github.com/matrix-org/go-neb/realms/jira/jira.go +++ b/src/github.com/matrix-org/go-neb/realms/jira/jira.go @@ -6,8 +6,12 @@ import ( "encoding/json" "encoding/pem" "errors" + log "github.com/Sirupsen/logrus" + "github.com/andygrunwald/go-jira" + "github.com/dghubble/oauth1" "github.com/matrix-org/go-neb/realms/jira/urls" "github.com/matrix-org/go-neb/types" + "golang.org/x/net/context" "net/http" ) @@ -49,12 +53,22 @@ func (r *jiraRealm) Register() error { if err != nil { return err } + r.JIRAEndpoint = ju.Base // Check to see if JIRA endpoint is valid by pinging an endpoint - err = jiraClient(ju, "") + cli, err := r.jiraClient(ju, "", true) if err != nil { return err } + info, err := jiraServerInfo(cli) + if err != nil { + return err + } + log.WithFields(log.Fields{ + "jira_url": ju.Base, + "title": info.ServerTitle, + "version": info.Version, + }).Print("Found JIRA endpoint") return nil } @@ -71,6 +85,47 @@ func (r *jiraRealm) AuthSession(id, userID, realmID string) types.AuthSession { return nil } +// jiraClient returns an authenticated jira.Client for the given userID. Returns an unauthenticated +// client if allowUnauth is true and no authenticated session is found, else returns an error. +func (r *jiraRealm) jiraClient(u urls.JIRAURL, userID string, allowUnauth bool) (*jira.Client, error) { + // TODO: Check if user has an auth session. Requires access token+secret + hasAuthSession := false + + if hasAuthSession { + // make an authenticated client + var cli *jira.Client + + auth := &oauth1.Config{ + ConsumerKey: r.ConsumerKey, + ConsumerSecret: r.ConsumerSecret, + CallbackURL: u.Base + "realms/redirect/" + r.id, + // TODO: In JIRA Cloud, the Authorization URL is only the Instance BASE_URL: + // https://BASE_URL.atlassian.net. + // It also does not require the + "/plugins/servlet/oauth/authorize" + // We should probably check the provided JIRA base URL to see if it is a cloud one + // then adjust accordingly. + Endpoint: oauth1.Endpoint{ + RequestTokenURL: u.Base + "plugins/servlet/oauth/request-token", + AuthorizeURL: u.Base + "plugins/servlet/oauth/authorize", + AccessTokenURL: u.Base + "plugins/servlet/oauth/access-token", + }, + Signer: &oauth1.RSASigner{ + PrivateKey: r.privateKey, + }, + } + + httpClient := auth.Client(context.TODO(), oauth1.NewToken("access_tokenTODO", "access_secretTODO")) + cli, err := jira.NewClient(httpClient, u.Base) + return cli, err + } else if allowUnauth { + // make an unauthenticated client + cli, err := jira.NewClient(nil, u.Base) + return cli, err + } else { + return nil, errors.New("No authenticated session found for " + userID) + } +} + func (r *jiraRealm) parsePrivateKey() error { pk, err := loadPrivateKey(r.PrivateKeyPEM) if err != nil { @@ -113,8 +168,22 @@ func publicKeyAsPEM(pkey *rsa.PrivateKey) (string, error) { return string(pem.EncodeToMemory(&block)), nil } -func jiraClient(u urls.JIRAURL, userID string) error { - return nil +// jiraServiceInfo is the HTTP response to JIRA_ENDPOINT/rest/api/2/serverInfo +type jiraServiceInfo struct { + ServerTitle string `json:"serverTitle"` + Version string `json:"version"` + VersionNumbers []int `json:"versionNumbers"` + BaseURL string `json:"baseUrl"` +} + +func jiraServerInfo(cli *jira.Client) (*jiraServiceInfo, error) { + var jsi jiraServiceInfo + req, _ := cli.NewRequest("GET", "rest/api/2/serverInfo", nil) + _, err := cli.Do(req, &jsi) + if err != nil { + return nil, err + } + return &jsi, nil } func init() { From 59f7fd12a36c5e752be4be9e35a037f2779af08a Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Wed, 10 Aug 2016 11:27:51 +0100 Subject: [PATCH 3/6] Formalise the response JSON to /configureAuthRealm for JIRA --- README.md | 24 ++++++++++++++++++- .../matrix-org/go-neb/realms/jira/jira.go | 4 ++++ .../go-neb/realms/jira/urls/urls.go | 4 ++-- 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 80dde8f..2f35077 100644 --- a/README.md +++ b/README.md @@ -154,15 +154,17 @@ Generate an RSA private key: (JIRA does not support key sizes >2048 bits) ```bash openssl genrsa -out privkey.pem 2048 +cat privkey.pem ``` - +Create the realm: ``` curl -X POST localhost:4050/admin/configureAuthRealm --data-binary '{ "ID": "jirarealm", "Type": "jira", "Config": { + "JIRAEndpoint": "matrix.org/jira/", "ConsumerName": "goneb", "ConsumerKey": "goneb", "ConsumerSecret": "random_long_string", @@ -172,7 +174,27 @@ curl -X POST localhost:4050/admin/configureAuthRealm --data-binary '{ ``` Returns: +```json +{ + "ID": "jirarealm", + "Type": "jira", + "OldConfig": nil, + "NewConfig": { + "JIRAEndpoint": "https://matrix.org/jira/", + "Server": "Matrix.org", + "Version": "6.3.5a", + "ConsumerName": "goneb", + "ConsumerKey": "goneb", + "ConsumerSecret": "random_long_string", + "PublicKeyPEM": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA39UhbOvQHEkBP9fGnhU+\neSObTWBDGWygVYzbcONOlqEOTJUN8gmnellWqJO45S4jB1vLLnuXiHqEWnmaShIv\nbUem3QnDDqghu0gfqXHMlQr5R8ZPorTt1F2idWy1wk5rVXeLKSG7uriYhDVOVS69\nWuefoW5v55b5YZV283v2jROjxHujgAsJA7k6tvpYiSXApUl6YHmECfBoiwG9bwIt\nkHwhZ/fG9i4H8/aOyr3WlaWbVeKX+m38lmYZvzQFRd7UPU7DuO6Aiqj7RxrbAvqq\ndPeoAvo6+V0TRPZ8YzKp2yQmDcGH69IbuKJ2BG1Qx8znZAvghKQ6P9Im+M4c7j9i\ndwIDAQAB\n-----END PUBLIC KEY-----\n", + "PrivateKeyPEM": "-----BEGIN RSA PRIVATE KEY-----\r\nMIIEowIBAAKCAQEA39UhbOvQHEkBP9fGnhU+eSObTWBDGWygVYzbcONOlqEOTJUN\r\n8gmnellWqJO45S4jB1vLLnuXiHqEWnmaShIvbUem3QnDDqghu0gfqXHMlQr5R8ZP\r\norTt1F2idWy1wk5rVXeLKSG7uriYhDVOVS69WuefoW5v55b5YZV283v2jROjxHuj\r\ngAsJA7k6tvpYiSXApUl6YHmECfBoiwG9bwItkHwhZ/fG9i4H8/aOyr3WlaWbVeKX\r\n+m38lmYZvzQFRd7UPU7DuO6Aiqj7RxrbAvqqdPeoAvo6+V0TRPZ8YzKp2yQmDcGH\r\n69IbuKJ2BG1Qx8znZAvghKQ6P9Im+M4c7j9iMG72VKhDgmEwFB1acOw0lpu1XE8R1wmwG\r\nZRl/xzri3LOW2Gpc77xu6fs3NIkzQw3v1ifYhX3OrVsCIRBbDjPQI3yYjkhGx24s\r\nVhhZ5S/TkGk3Kw59bDC6KGqAuQAwX9req2l1NiuNaPU9rE7tf6Bk\r\n-----END RSA PRIVATE KEY-----" + } +} +``` +The `PublicKeyPEM` must be manually inserted into the "Application Links" section under +JIRA Admin Settings by a JIRA admin on the target JIRA installation. Once that is complete, +users can OAuth on the target JIRA installation. ### Make a request for JIRA Auth diff --git a/src/github.com/matrix-org/go-neb/realms/jira/jira.go b/src/github.com/matrix-org/go-neb/realms/jira/jira.go index 15eb440..795f71e 100644 --- a/src/github.com/matrix-org/go-neb/realms/jira/jira.go +++ b/src/github.com/matrix-org/go-neb/realms/jira/jira.go @@ -19,6 +19,8 @@ type jiraRealm struct { id string privateKey *rsa.PrivateKey JIRAEndpoint string + Server string // clobbered based on /serverInfo request + Version string // clobbered based on /serverInfo request ConsumerName string ConsumerKey string ConsumerSecret string @@ -69,6 +71,8 @@ func (r *jiraRealm) Register() error { "title": info.ServerTitle, "version": info.Version, }).Print("Found JIRA endpoint") + r.Server = info.ServerTitle + r.Version = info.Version return nil } diff --git a/src/github.com/matrix-org/go-neb/realms/jira/urls/urls.go b/src/github.com/matrix-org/go-neb/realms/jira/urls/urls.go index 1dd1536..445b73b 100644 --- a/src/github.com/matrix-org/go-neb/realms/jira/urls/urls.go +++ b/src/github.com/matrix-org/go-neb/realms/jira/urls/urls.go @@ -1,9 +1,9 @@ // Package urls handles converting between various JIRA URL representations in a consistent way. There exists three main -// types of JIRA URL which Scalar cares about: +// types of JIRA URL which Go-NEB cares about: // - URL Keys => matrix.org/jira // - Base URLs => https://matrix.org/jira/ // - REST URLs => https://matrix.org/jira/rest/api/2/issue/12680 -// When making outbound requests to JIRA, Scalar needs to use the Base URL representation. Likewise, when Scalar +// When making outbound requests to JIRA, Go-NEB needs to use the Base URL representation. Likewise, when Go-NEB // sends Matrix messages with JIRA URLs in them, the Base URL needs to be used to form the URL. The URL Key is // used to determine equivalence of various JIRA installations and is mainly required when searching the database. // The REST URLs are present on incoming webhook events and are the only way to map the event to a JIRA installation. From 4507b696a72c8ffdcdf828d56f89a593a068bd57 Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Wed, 10 Aug 2016 11:29:12 +0100 Subject: [PATCH 4/6] More things to insert --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 2f35077..8f411ee 100644 --- a/README.md +++ b/README.md @@ -192,9 +192,9 @@ Returns: } ``` -The `PublicKeyPEM` must be manually inserted into the "Application Links" section under -JIRA Admin Settings by a JIRA admin on the target JIRA installation. Once that is complete, -users can OAuth on the target JIRA installation. +The `ConsumerKey`, `ConsumerSecret`, `ConsumerName` and `PublicKeyPEM` must be manually inserted +into the "Application Links" section under JIRA Admin Settings by a JIRA admin on the target +JIRA installation. Once that is complete, users can OAuth on the target JIRA installation. ### Make a request for JIRA Auth From 9fe0512d9f189801e74e34ed00b98992d28654f6 Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Wed, 10 Aug 2016 11:30:37 +0100 Subject: [PATCH 5/6] s/nil/null/ --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8f411ee..6bf68f3 100644 --- a/README.md +++ b/README.md @@ -178,7 +178,7 @@ Returns: { "ID": "jirarealm", "Type": "jira", - "OldConfig": nil, + "OldConfig": null, "NewConfig": { "JIRAEndpoint": "https://matrix.org/jira/", "Server": "Matrix.org", From c6483215f65222acc5cda2d976780ebd424287b9 Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Wed, 10 Aug 2016 11:51:29 +0100 Subject: [PATCH 6/6] Twiddle order of test table fields --- .../go-neb/realms/jira/urls/urls_test.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/github.com/matrix-org/go-neb/realms/jira/urls/urls_test.go b/src/github.com/matrix-org/go-neb/realms/jira/urls/urls_test.go index 288b239..a7cad52 100644 --- a/src/github.com/matrix-org/go-neb/realms/jira/urls/urls_test.go +++ b/src/github.com/matrix-org/go-neb/realms/jira/urls/urls_test.go @@ -6,24 +6,24 @@ import ( var urltests = []struct { in string - outKey string outBase string + outKey string outRaw string }{ // valid url key as input - {"matrix.org/jira", "matrix.org/jira", "https://matrix.org/jira/", "matrix.org/jira"}, + {"matrix.org/jira", "https://matrix.org/jira/", "matrix.org/jira", "matrix.org/jira"}, // valid url base as input - {"https://matrix.org/jira/", "matrix.org/jira", "https://matrix.org/jira/", "https://matrix.org/jira/"}, + {"https://matrix.org/jira/", "https://matrix.org/jira/", "matrix.org/jira", "https://matrix.org/jira/"}, // valid rest url as input - {"https://matrix.org/jira/rest/api/2/issue/12680", "matrix.org/jira", "https://matrix.org/jira/", "https://matrix.org/jira/rest/api/2/issue/12680"}, + {"https://matrix.org/jira/rest/api/2/issue/12680", "https://matrix.org/jira/", "matrix.org/jira", "https://matrix.org/jira/rest/api/2/issue/12680"}, // missing trailing slash as input - {"https://matrix.org/jira", "matrix.org/jira", "https://matrix.org/jira/", "https://matrix.org/jira"}, + {"https://matrix.org/jira", "https://matrix.org/jira/", "matrix.org/jira", "https://matrix.org/jira"}, // missing protocol but with trailing slash - {"matrix.org/jira/", "matrix.org/jira", "https://matrix.org/jira/", "matrix.org/jira/"}, + {"matrix.org/jira/", "https://matrix.org/jira/", "matrix.org/jira", "matrix.org/jira/"}, // no jira path as base url (subdomain) - {"https://jira.matrix.org", "jira.matrix.org", "https://jira.matrix.org/", "https://jira.matrix.org"}, + {"https://jira.matrix.org", "https://jira.matrix.org/", "jira.matrix.org", "https://jira.matrix.org"}, // explicit http as input - {"http://matrix.org/jira", "matrix.org/jira", "http://matrix.org/jira/", "http://matrix.org/jira"}, + {"http://matrix.org/jira", "http://matrix.org/jira/", "matrix.org/jira", "http://matrix.org/jira"}, } func TestParseJIRAURL(t *testing.T) { @@ -36,7 +36,7 @@ func TestParseJIRAURL(t *testing.T) { t.Fatalf("ParseJIRAURL(%s) => Key: Want %s got %s", urltest.in, urltest.outKey, jURL.Key) } if jURL.Base != urltest.outBase { - t.Fatalf("ParseJIRAURL(%s) => Base: Want %s got %s", urltest.in, urltest.outBase, jURL.Key) + t.Fatalf("ParseJIRAURL(%s) => Base: Want %s got %s", urltest.in, urltest.outBase, jURL.Base) } if jURL.Raw != urltest.outRaw { t.Fatalf("ParseJIRAURL(%s) => Raw: Want %s got %s", urltest.in, urltest.outRaw, jURL.Raw)