Skip to content
This repository was archived by the owner on Sep 30, 2024. It is now read-only.

Commit d3a3d72

Browse files
authored
Add support for Bitbucket Server OAuth2 (#64179)
Docs here: sourcegraph/docs#561 This PR adds support for using Bitbucket Server OAuth2 application links for sign-in and permission syncing. When used for permission syncing, the user's oauth token is used to fetch user permissions (and now permissions are fetched via the server). ## Test plan Tests added and updated. ## Changelog - Sourcegraph now supports Bitbucket Server OAuth2 application links for user sign-in and permission syncing.
1 parent 56e1f11 commit d3a3d72

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+1975
-169
lines changed

Diff for: client/web/src/auth/SignInPage.tsx

+3
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,9 @@ const ProviderIcon: React.FunctionComponent<{ serviceType: AuthProvider['service
222222
case 'bitbucketCloud': {
223223
return <Icon aria-hidden={true} svgPath={mdiBitbucket} />
224224
}
225+
case 'bitbucketServer': {
226+
return <Icon aria-hidden={true} svgPath={mdiBitbucket} />
227+
}
225228
case 'azuredevops': {
226229
return <Icon aria-hidden={true} svgPath={mdiMicrosoftAzureDevops} />
227230
}

Diff for: client/web/src/auth/SignUpForm.tsx

+2
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,8 @@ export const SignUpForm: React.FunctionComponent<React.PropsWithChildren<SignUpF
226226
<Icon aria-hidden={true} svgPath={mdiGitlab} />
227227
) : provider.serviceType === 'bitbucketCloud' ? (
228228
<Icon aria-hidden={true} svPath={mdiBitbucket} />
229+
) : provider.serviceType === 'bitbucketServer' ? (
230+
<Icon aria-hidden={true} svgPath={mdiBitbucket} />
229231
) : null}{' '}
230232
Continue with {provider.displayName}
231233
</Button>

Diff for: client/web/src/components/externalAccounts/externalAccounts.ts

+4
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ export const defaultExternalAccounts: Record<ExternalAccountKind, ExternalAccoun
5151
title: 'Bitbucket Cloud',
5252
icon: BitbucketIcon,
5353
},
54+
bitbucketServer: {
55+
title: 'Bitbucket Server',
56+
icon: BitbucketIcon,
57+
},
5458
gerrit: {
5559
title: 'Gerrit',
5660
icon: GerritIcon,

Diff for: client/web/src/jscontext.ts

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export interface AuthProvider {
2323
| 'github'
2424
| 'gitlab'
2525
| 'bitbucketCloud'
26+
| 'bitbucketServer'
2627
| 'http-header'
2728
| 'openidconnect'
2829
| 'sourcegraph-operator'

Diff for: client/web/src/repo/utils.tsx

+3
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ export const stringToCodeHostType = (codeHostType: string): CodeHostType => {
3434
case 'bitbucketCloud': {
3535
return CodeHostType.BITBUCKETCLOUD
3636
}
37+
case 'bitbucketServer': {
38+
return CodeHostType.BITBUCKETSERVER
39+
}
3740
case 'gitolite': {
3841
return CodeHostType.GITOLITE
3942
}

Diff for: client/web/src/util/constants.ts

+1
Original file line numberDiff line numberDiff line change
@@ -73,4 +73,5 @@ export const V2AuthProviderTypes: { [k in AuthProvider['serviceType']]: number }
7373
builtin: 7,
7474
gerrit: 8,
7575
azuredevops: 9,
76+
bitbucketServer: 10,
7677
}

Diff for: cmd/frontend/graphqlbackend/external_account_data_resolver_test.go

+4
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ func (m mockAuthnProvider) CachedInfo() *providers.Info {
3838
// return &providers.Info{ServiceID: m.serviceID}
3939
}
4040

41+
func (m mockAuthnProvider) Type() providers.ProviderType {
42+
return providers.ProviderTypeOAuth
43+
}
44+
4145
type mockAuthnProviderUser struct {
4246
Username string `json:"username,omitempty"`
4347
ID int32 `json:"id,omitempty"`

Diff for: cmd/frontend/internal/auth/BUILD.bazel

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ go_library(
1111
"//cmd/frontend/internal/auth/authutil",
1212
"//cmd/frontend/internal/auth/azureoauth",
1313
"//cmd/frontend/internal/auth/bitbucketcloudoauth",
14+
"//cmd/frontend/internal/auth/bitbucketserveroauth",
1415
"//cmd/frontend/internal/auth/gerrit",
1516
"//cmd/frontend/internal/auth/githuboauth",
1617
"//cmd/frontend/internal/auth/gitlaboauth",

Diff for: cmd/frontend/internal/auth/azureoauth/middleware.go

-7
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,8 @@ import (
77
"github.com/sourcegraph/sourcegraph/cmd/frontend/internal/auth/oauth"
88
"github.com/sourcegraph/sourcegraph/internal/database"
99
"github.com/sourcegraph/sourcegraph/internal/extsvc"
10-
"github.com/sourcegraph/sourcegraph/schema"
1110
)
1211

13-
func init() {
14-
oauth.AddIsOAuth(func(p schema.AuthProviders) bool {
15-
return p.AzureDevOps != nil
16-
})
17-
}
18-
1912
func Middleware(db database.DB) *auth.Middleware {
2013
return &auth.Middleware{
2114
API: func(next http.Handler) http.Handler {

Diff for: cmd/frontend/internal/auth/bitbucketcloudoauth/middleware.go

-7
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,10 @@ import (
77
"github.com/sourcegraph/sourcegraph/cmd/frontend/internal/auth/oauth"
88
"github.com/sourcegraph/sourcegraph/internal/database"
99
"github.com/sourcegraph/sourcegraph/internal/extsvc"
10-
"github.com/sourcegraph/sourcegraph/schema"
1110
)
1211

1312
const authPrefix = auth.AuthURLPrefix + "/bitbucketcloud"
1413

15-
func init() {
16-
oauth.AddIsOAuth(func(p schema.AuthProviders) bool {
17-
return p.Bitbucketcloud != nil
18-
})
19-
}
20-
2114
func Middleware(db database.DB) *auth.Middleware {
2215
return &auth.Middleware{
2316
API: func(next http.Handler) http.Handler {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
load("//dev:go_defs.bzl", "go_test")
2+
load("@io_bazel_rules_go//go:def.bzl", "go_library")
3+
4+
go_library(
5+
name = "bitbucketserveroauth",
6+
srcs = [
7+
"config.go",
8+
"middleware.go",
9+
"provider.go",
10+
"session.go",
11+
],
12+
importpath = "github.com/sourcegraph/sourcegraph/cmd/frontend/internal/auth/bitbucketserveroauth",
13+
visibility = ["//cmd/frontend:__subpackages__"],
14+
deps = [
15+
"//cmd/frontend/auth",
16+
"//cmd/frontend/hubspot",
17+
"//cmd/frontend/hubspot/hubspotutil",
18+
"//cmd/frontend/internal/auth/oauth",
19+
"//cmd/frontend/internal/auth/providers",
20+
"//cmd/frontend/internal/auth/session",
21+
"//internal/actor",
22+
"//internal/collections",
23+
"//internal/conf",
24+
"//internal/conf/conftypes",
25+
"//internal/database",
26+
"//internal/extsvc",
27+
"//internal/extsvc/auth",
28+
"//internal/extsvc/bitbucketserver",
29+
"//internal/licensing",
30+
"//internal/telemetry/telemetryrecorder",
31+
"//lib/errors",
32+
"//schema",
33+
"@com_github_dghubble_gologin_v2//:gologin",
34+
"@com_github_dghubble_gologin_v2//bitbucket",
35+
"@com_github_dghubble_gologin_v2//oauth2",
36+
"@com_github_sourcegraph_log//:log",
37+
"@org_golang_x_oauth2//:oauth2",
38+
],
39+
)
40+
41+
go_test(
42+
name = "bitbucketserveroauth_test",
43+
srcs = [
44+
"config_test.go",
45+
"middleware_test.go",
46+
"session_test.go",
47+
],
48+
embed = [":bitbucketserveroauth"],
49+
tags = ["requires-network"],
50+
deps = [
51+
"//cmd/frontend/auth",
52+
"//cmd/frontend/internal/auth/oauth",
53+
"//cmd/frontend/internal/auth/providers",
54+
"//cmd/frontend/internal/auth/session",
55+
"//internal/actor",
56+
"//internal/conf",
57+
"//internal/database",
58+
"//internal/database/dbmocks",
59+
"//internal/database/dbtest",
60+
"//internal/extsvc",
61+
"//internal/extsvc/bitbucketserver",
62+
"//internal/httpcli",
63+
"//internal/ratelimit",
64+
"//lib/errors",
65+
"//schema",
66+
"@com_github_google_go_cmp//cmp",
67+
"@com_github_google_go_cmp//cmp/cmpopts",
68+
"@com_github_sourcegraph_log//logtest",
69+
"@org_golang_x_oauth2//:oauth2",
70+
],
71+
)
+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package bitbucketserveroauth
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/sourcegraph/log"
7+
8+
"github.com/sourcegraph/sourcegraph/cmd/frontend/internal/auth/providers"
9+
"github.com/sourcegraph/sourcegraph/internal/collections"
10+
"github.com/sourcegraph/sourcegraph/internal/conf"
11+
"github.com/sourcegraph/sourcegraph/internal/conf/conftypes"
12+
"github.com/sourcegraph/sourcegraph/internal/database"
13+
"github.com/sourcegraph/sourcegraph/internal/licensing"
14+
"github.com/sourcegraph/sourcegraph/schema"
15+
)
16+
17+
func Init(logger log.Logger, db database.DB) {
18+
const pkgName = "bitbucketserveroauth"
19+
logger = logger.Scoped(pkgName)
20+
conf.ContributeValidator(func(cfg conftypes.SiteConfigQuerier) conf.Problems {
21+
_, problems := parseConfig(logger, cfg, db)
22+
return problems
23+
})
24+
25+
go conf.Watch(func() {
26+
newProviders, _ := parseConfig(logger, conf.Get(), db)
27+
if len(newProviders) == 0 {
28+
providers.Update(pkgName, nil)
29+
return
30+
}
31+
32+
if err := licensing.Check(licensing.FeatureSSO); err != nil {
33+
logger.Error("Check license for SSO (Bitbucket Server OAuth)", log.Error(err))
34+
providers.Update(pkgName, nil)
35+
return
36+
}
37+
38+
newProvidersList := make([]providers.Provider, 0, len(newProviders))
39+
for _, p := range newProviders {
40+
newProvidersList = append(newProvidersList, p.Provider)
41+
}
42+
providers.Update(pkgName, newProvidersList)
43+
})
44+
}
45+
46+
type Provider struct {
47+
*schema.BitbucketServerAuthProvider
48+
providers.Provider
49+
}
50+
51+
func parseConfig(logger log.Logger, cfg conftypes.SiteConfigQuerier, db database.DB) (ps []Provider, problems conf.Problems) {
52+
existingProviders := make(collections.Set[string])
53+
54+
for _, pr := range cfg.SiteConfig().AuthProviders {
55+
if pr.Bitbucketserver == nil {
56+
continue
57+
}
58+
59+
provider, providerProblems := parseProvider(logger, pr.Bitbucketserver, db, pr)
60+
problems = append(problems, conf.NewSiteProblems(providerProblems...)...)
61+
if provider == nil {
62+
continue
63+
}
64+
65+
if existingProviders.Has(provider.CachedInfo().UniqueID()) {
66+
problems = append(problems, conf.NewSiteProblems(fmt.Sprintf(`Cannot have more than one Bitbucket Server auth provider with url %q and client ID %q, only the first one will be used`, provider.ServiceID, provider.CachedInfo().ClientID))...)
67+
continue
68+
}
69+
70+
ps = append(ps, Provider{
71+
BitbucketServerAuthProvider: pr.Bitbucketserver,
72+
Provider: provider,
73+
})
74+
existingProviders.Add(provider.CachedInfo().UniqueID())
75+
}
76+
return ps, problems
77+
}

0 commit comments

Comments
 (0)