Skip to content

Commit

Permalink
feat(onAuth): remove OAuth2 variant, support raw HTTP headers, endles…
Browse files Browse the repository at this point in the history
…s retry, canceling (isomorphic-git#1054)

BREAKING CHANGE: The `token` and `oauth2format` properties have been removed from the GitAuth interface, which makes it much simpler and and eliminates a dozen GitErrors handling specific edge cases.

A `headers` property has been added to the GitAuth interface. This makes `onAuth` much more powerful because you can inject whatever HTTP headers you want.

The `onAuthFailed` callback now lets you return a GitAuth object. This means you can keep retrying to authenticate as many times as you like.

A `cancel` property has been added to the GitAuth interface. This means you gracefully give up authenticating and the function will throw an E.UserCancelledError instead of an E.HTTPError.
  • Loading branch information
billiegoose authored Feb 19, 2020
1 parent 429fde1 commit f51e489
Show file tree
Hide file tree
Showing 24 changed files with 440 additions and 314 deletions.
7 changes: 4 additions & 3 deletions __tests__/test-hosting-providers.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,8 @@ describe('Hosting Providers', () => {
// with "public_repo" access. The only repo it has write access to is
// https://github.com/isomorphic-git/test.empty
// It is stored reversed to avoid Github's auto-revoking feature.
const token = reverse('e8df25b340c98b7eec57a4976bd9074b93a7dc1c')
const password = reverse('e8df25b340c98b7eec57a4976bd9074b93a7dc1c')
const username = 'isomorphic-git-test-push'
it('fetch', async () => {
// Setup
const { fs, gitdir } = await makeFixture('test-hosting-providers')
Expand All @@ -163,7 +164,7 @@ describe('Hosting Providers', () => {
corsProxy: process.browser ? `http://${localhost}:9999` : undefined,
remote: 'github',
ref: 'master',
onAuth: () => ({ token }),
onAuth: () => ({ username, password }),
})
expect(res).toBeTruthy()
expect(res.defaultBranch).toBe('refs/heads/test')
Expand All @@ -181,7 +182,7 @@ describe('Hosting Providers', () => {
remote: 'github',
ref: 'master',
force: true,
onAuth: () => ({ token }),
onAuth: () => ({ username, password }),
})
expect(res).toBeTruthy()
expect(res.ok).toBe(true)
Expand Down
258 changes: 214 additions & 44 deletions __tests__/test-push.js
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ describe('push', () => {
}
expect(error).toContain('401')
})

it('onAuthSuccess', async () => {
// Setup
const { fs, gitdir } = await makeFixture('test-push')
Expand All @@ -279,50 +280,49 @@ describe('push', () => {
value: `http://${localhost}:8888/test-push-server-auth.git`,
})
// Test
let fillCalled = false
let approvedCalled = false
let rejectedCalled = false
let onAuthArgs = null
let onAuthSuccessArgs = null
let onAuthFailureArgs = null
const onAuthArgs = []
const onAuthSuccessArgs = []
const onAuthFailureArgs = []
await push({
fs,
http,
gitdir,
remote: 'auth',
ref: 'master',
async onAuth(...args) {
fillCalled = true
onAuthArgs = args
onAuthArgs.push(args)
return {
username: 'testuser',
password: 'testpassword',
}
},
async onAuthSuccess(...args) {
approvedCalled = true
onAuthSuccessArgs = args
onAuthSuccessArgs.push(args)
},
async onAuthFailure(...args) {
rejectedCalled = true
onAuthFailureArgs = args
onAuthFailureArgs.push(args)
},
})
expect(fillCalled).toBe(true)
expect(approvedCalled).toBe(true)
expect(rejectedCalled).toBe(false)
expect(onAuthArgs).toEqual([
`http://${localhost}:8888/test-push-server-auth.git`,
[
`http://${localhost}:8888/test-push-server-auth.git`,
{
headers: {},
},
],
])
expect(onAuthSuccessArgs).toEqual([
`http://${localhost}:8888/test-push-server-auth.git`,
{
username: 'testuser',
password: 'testpassword',
},
[
`http://${localhost}:8888/test-push-server-auth.git`,
{
username: 'testuser',
password: 'testpassword',
},
],
])
expect(onAuthFailureArgs).toBeNull()
expect(onAuthFailureArgs).toEqual([])
})

it('onAuthFailure', async () => {
// Setup
const { fs, gitdir } = await makeFixture('test-push')
Expand All @@ -333,14 +333,10 @@ describe('push', () => {
value: `http://${localhost}:8888/test-push-server-auth.git`,
})
// Test
let fillCalled = false
let approvedCalled = false
let rejectedCalled = false
let err
let onAuthArgs = null
let onAuthSuccessArgs = null
let onAuthFailureArgs = null

const onAuthArgs = []
const onAuthSuccessArgs = []
const onAuthFailureArgs = []
try {
await push({
fs,
Expand All @@ -349,40 +345,214 @@ describe('push', () => {
remote: 'auth',
ref: 'master',
async onAuth(...args) {
fillCalled = true
onAuthArgs = args
onAuthArgs.push(args)
return {
username: 'testuser',
password: 'NoT_rIgHt',
}
},
async onAuthSuccess(...args) {
approvedCalled = true
onAuthSuccessArgs = args
onAuthSuccessArgs.push(args)
},
async onAuthFailure(...args) {
rejectedCalled = true
onAuthFailureArgs = args
onAuthFailureArgs.push(args)
switch (onAuthFailureArgs.length) {
case 1:
return {
username: 'testuser',
password: 'St1ll_NoT_rIgHt',
}
case 2:
return {
headers: {
Authorization: 'Bearer Big Bear',
'X-Authorization': 'supersecret',
},
}
}
},
})
} catch (e) {
err = e
}
expect(err).toBeDefined()
expect(err.code).toBe(E.HTTPError)
expect(fillCalled).toBe(true)
expect(approvedCalled).toBe(false)
expect(rejectedCalled).toBe(true)
expect(onAuthArgs).toEqual([
`http://${localhost}:8888/test-push-server-auth.git`,
[
`http://${localhost}:8888/test-push-server-auth.git`,
{
headers: {},
},
],
])
expect(onAuthSuccessArgs).toBeNull()
expect(onAuthSuccessArgs).toEqual([])
expect(onAuthFailureArgs).toEqual([
`http://${localhost}:8888/test-push-server-auth.git`,
{
username: 'testuser',
password: 'NoT_rIgHt',
[
`http://${localhost}:8888/test-push-server-auth.git`,
{
headers: {
Authorization: 'Basic dGVzdHVzZXI6Tm9UX3JJZ0h0',
},
username: 'testuser',
password: 'NoT_rIgHt',
},
],
[
`http://${localhost}:8888/test-push-server-auth.git`,
{
headers: {
Authorization: 'Basic dGVzdHVzZXI6U3QxbGxfTm9UX3JJZ0h0',
},
username: 'testuser',
password: 'St1ll_NoT_rIgHt',
},
],
[
`http://${localhost}:8888/test-push-server-auth.git`,
{
headers: {
Authorization: 'Bearer Big Bear',
'X-Authorization': 'supersecret',
},
},
],
])
})

it('onAuthFailure then onAuthSuccess', async () => {
// Setup
const { fs, gitdir } = await makeFixture('test-push')
await setConfig({
fs,
gitdir,
path: 'remote.auth.url',
value: `http://${localhost}:8888/test-push-server-auth.git`,
})
// Test
const onAuthArgs = []
const onAuthSuccessArgs = []
const onAuthFailureArgs = []
await push({
fs,
http,
gitdir,
remote: 'auth',
ref: 'master',
async onAuth(...args) {
onAuthArgs.push(args)
return {
username: 'testuser',
password: 'NoT_rIgHt',
}
},
async onAuthSuccess(...args) {
onAuthSuccessArgs.push(args)
},
async onAuthFailure(...args) {
onAuthFailureArgs.push(args)
switch (onAuthFailureArgs.length) {
case 1:
return {
username: 'testuser',
password: 'St1ll_NoT_rIgHt',
}
case 2:
return {
username: 'testuser',
password: 'testpassword',
}
}
},
})
expect(onAuthArgs).toEqual([
[
`http://${localhost}:8888/test-push-server-auth.git`,
{
headers: {},
},
],
])
expect(onAuthSuccessArgs).toEqual([
[
`http://${localhost}:8888/test-push-server-auth.git`,
{
username: 'testuser',
password: 'testpassword',
},
],
])
expect(onAuthFailureArgs).toEqual([
[
`http://${localhost}:8888/test-push-server-auth.git`,
{
headers: {
Authorization: 'Basic dGVzdHVzZXI6Tm9UX3JJZ0h0',
},
username: 'testuser',
password: 'NoT_rIgHt',
},
],
[
`http://${localhost}:8888/test-push-server-auth.git`,
{
headers: {
Authorization: 'Basic dGVzdHVzZXI6U3QxbGxfTm9UX3JJZ0h0',
},
username: 'testuser',
password: 'St1ll_NoT_rIgHt',
},
],
])
})

it('onAuth + cancel', async () => {
// Setup
const { fs, gitdir } = await makeFixture('test-push')
await setConfig({
fs,
gitdir,
path: 'remote.auth.url',
value: `http://${localhost}:8888/test-push-server-auth.git`,
})
// Test
let err
const onAuthArgs = []
const onAuthSuccessArgs = []
const onAuthFailureArgs = []
try {
await push({
fs,
http,
gitdir,
remote: 'auth',
ref: 'master',
async onAuth(...args) {
onAuthArgs.push(args)
return {
cancel: true,
}
},
async onAuthSuccess(...args) {
onAuthSuccessArgs.push(args)
},
async onAuthFailure(...args) {
onAuthFailureArgs.push(args)
},
})
} catch (e) {
err = e
}
expect(err).toBeDefined()
expect(err.code).toBe(E.UserCancelledError)
expect(onAuthArgs).toEqual([
[
`http://${localhost}:8888/test-push-server-auth.git`,
{
headers: {},
},
],
])
expect(onAuthSuccessArgs).toEqual([])
expect(onAuthFailureArgs).toEqual([])
})
})
Loading

0 comments on commit f51e489

Please sign in to comment.