Skip to content

Commit 7ae9903

Browse files
authored
fixes #16 (#20)
* fixes #16 - allow authenticate to handle promises * fixes lint * fixes lcov location
1 parent df8d7fe commit 7ae9903

File tree

8 files changed

+149
-50
lines changed

8 files changed

+149
-50
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ script:
77
- npm install lcov-server -g
88
- npm run lint
99
- npm run coverage
10-
- cat coverage/lcov.info | lcov-server-cli --url https://lcov-server.herokuapp.com
10+
- cat coverage/lcov.info | lcov-server --upload https://lcov-server.herokuapp.com
1111
node_js:
1212
- "6"
1313
- "8"

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# Unreleased
2+
3+
- allow authenticate to handle promises
4+
15
# 0.3.0
26

37
- removes authentication logic and makes it a configurable middleware

docs/code/Git.html

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ <h4 class="name" id="Git"><span class="type-signature"></span>new Git<span class
6565

6666
<dt class="tag-source">Source:</dt>
6767
<dd class="tag-source"><ul class="dummy"><li>
68-
<a href="git.js.html">git.js</a>, <a href="git.js.html#line131">line 131</a>
68+
<a href="git.js.html">git.js</a>, <a href="git.js.html#line141">line 141</a>
6969
</li></ul></dd>
7070

7171

@@ -315,8 +315,18 @@ <h6>Properties</h6>
315315

316316
<td class="description last"><p>a function that has the following arguments (repo, username, password, next) and will be called when a request comes through if set</p>
317317
<pre class="prettyprint source"><code> authenticate: (type, repo, username, password, next) => {
318-
console.log(type, repo, username, password); // eslint-disable-line
318+
console.log(type, repo, username, password);
319319
next();
320+
}
321+
// alternatively you can also pass authenticate a promise
322+
authenticate: (type, repo, username, password, next) => {
323+
console.log(type, repo, username, password);
324+
return new Promise((resolve, reject) => {
325+
if(username === 'foo') {
326+
return resolve();
327+
}
328+
return reject(&quot;sorry you don't have access to this content&quot;);
329+
});
320330
}</code></pre></td>
321331
</tr>
322332

docs/code/git.js.html

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,19 @@ <h1 class="page-title">git.js</h1>
6464
* @param {Function} options.authenticate - a function that has the following arguments (repo, username, password, next) and will be called when a request comes through if set
6565
*
6666
authenticate: (type, repo, username, password, next) => {
67-
console.log(type, repo, username, password); // eslint-disable-line
67+
console.log(type, repo, username, password);
6868
next();
6969
}
70+
// alternatively you can also pass authenticate a promise
71+
authenticate: (type, repo, username, password, next) => {
72+
console.log(type, repo, username, password);
73+
return new Promise((resolve, reject) => {
74+
if(username === 'foo') {
75+
return resolve();
76+
}
77+
return reject("sorry you don't have access to this content");
78+
});
79+
}
7080
* @param {Boolean=} options.checkout - If `opts.checkout` is true, create and expected checked-out repos instead of
7181
bare repos
7282
* @return {Git}
@@ -301,32 +311,36 @@ <h1 class="page-title">git.js</h1>
301311
}
302312

303313
var repoName = parseGitName(m[1]);
314+
var next = (error) => {
315+
if(error) {
316+
res.setHeader("Content-Type", 'text/plain');
317+
res.setHeader("WWW-Authenticate", 'Basic realm="authorization needed"');
318+
res.writeHead(401);
319+
res.end(error);
320+
return;
321+
} else {
322+
return infoResponse({
323+
repos: self,
324+
repo: repo,
325+
service: service,
326+
}, req, res);
327+
}
328+
}
304329

305330
// check if the repo is authenticated
306331
if(this.authenticate) {
307332
basicAuth(req, res, (username, password) => {
308-
this.authenticate(service === 'upload-pack' ? 'upload' : 'download', repoName, username, password, (error) => {
309-
if(error) {
310-
res.setHeader("Content-Type", 'text/plain');
311-
res.setHeader("WWW-Authenticate", 'Basic realm="authorization needed"');
312-
res.writeHead(401);
313-
res.end(error);
314-
return;
315-
} else {
316-
return infoResponse({
317-
repos: self,
318-
repo: repo,
319-
service: service,
320-
}, req, res);
321-
}
333+
var promise = this.authenticate(service === 'upload-pack' ? 'upload' : 'download', repoName, username, password, (error) => {
334+
return next(error);
322335
});
336+
if(promise instanceof Promise) {
337+
return promise
338+
.then(next)
339+
.catch(next)
340+
}
323341
});
324342
} else {
325-
return infoResponse({
326-
repos: self,
327-
repo: repo,
328-
service: service,
329-
}, req, res);
343+
return next();
330344
}
331345
},
332346
function(req, res) {

docs/code/global.html

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ <h4 class="name" id="create"><span class="type-signature"></span>create<span cla
127127

128128
<dt class="tag-source">Source:</dt>
129129
<dd class="tag-source"><ul class="dummy"><li>
130-
<a href="git.js.html">git.js</a>, <a href="git.js.html#line191">line 191</a>
130+
<a href="git.js.html">git.js</a>, <a href="git.js.html#line201">line 201</a>
131131
</li></ul></dd>
132132

133133

@@ -303,7 +303,7 @@ <h4 class="name" id="exists"><span class="type-signature"></span>exists<span cla
303303

304304
<dt class="tag-source">Source:</dt>
305305
<dd class="tag-source"><ul class="dummy"><li>
306-
<a href="git.js.html">git.js</a>, <a href="git.js.html#line165">line 165</a>
306+
<a href="git.js.html">git.js</a>, <a href="git.js.html#line175">line 175</a>
307307
</li></ul></dd>
308308

309309

@@ -479,7 +479,7 @@ <h4 class="name" id="handle"><span class="type-signature"></span>handle<span cla
479479

480480
<dt class="tag-source">Source:</dt>
481481
<dd class="tag-source"><ul class="dummy"><li>
482-
<a href="git.js.html">git.js</a>, <a href="git.js.html#line232">line 232</a>
482+
<a href="git.js.html">git.js</a>, <a href="git.js.html#line242">line 242</a>
483483
</li></ul></dd>
484484

485485

@@ -635,7 +635,7 @@ <h4 class="name" id="list"><span class="type-signature"></span>list<span class="
635635

636636
<dt class="tag-source">Source:</dt>
637637
<dd class="tag-source"><ul class="dummy"><li>
638-
<a href="git.js.html">git.js</a>, <a href="git.js.html#line150">line 150</a>
638+
<a href="git.js.html">git.js</a>, <a href="git.js.html#line160">line 160</a>
639639
</li></ul></dd>
640640

641641

@@ -768,7 +768,7 @@ <h4 class="name" id="mkdir"><span class="type-signature"></span>mkdir<span class
768768

769769
<dt class="tag-source">Source:</dt>
770770
<dd class="tag-source"><ul class="dummy"><li>
771-
<a href="git.js.html">git.js</a>, <a href="git.js.html#line174">line 174</a>
771+
<a href="git.js.html">git.js</a>, <a href="git.js.html#line184">line 184</a>
772772
</li></ul></dd>
773773

774774

lib/git.js

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,19 @@ class Git extends EventEmitter {
2525
* @param {Function} options.authenticate - a function that has the following arguments (repo, username, password, next) and will be called when a request comes through if set
2626
*
2727
authenticate: (type, repo, username, password, next) => {
28-
console.log(type, repo, username, password); // eslint-disable-line
28+
console.log(type, repo, username, password);
2929
next();
3030
}
31+
// alternatively you can also pass authenticate a promise
32+
authenticate: (type, repo, username, password, next) => {
33+
console.log(type, repo, username, password);
34+
return new Promise((resolve, reject) => {
35+
if(username === 'foo') {
36+
return resolve();
37+
}
38+
return reject("sorry you don't have access to this content");
39+
});
40+
}
3141
* @param {Boolean=} options.checkout - If `opts.checkout` is true, create and expected checked-out repos instead of
3242
bare repos
3343
* @return {Git}
@@ -262,32 +272,36 @@ class Git extends EventEmitter {
262272
}
263273

264274
var repoName = parseGitName(m[1]);
275+
var next = (error) => {
276+
if(error) {
277+
res.setHeader("Content-Type", 'text/plain');
278+
res.setHeader("WWW-Authenticate", 'Basic realm="authorization needed"');
279+
res.writeHead(401);
280+
res.end(error);
281+
return;
282+
} else {
283+
return infoResponse({
284+
repos: self,
285+
repo: repo,
286+
service: service,
287+
}, req, res);
288+
}
289+
};
265290

266291
// check if the repo is authenticated
267292
if(this.authenticate) {
268293
basicAuth(req, res, (username, password) => {
269-
this.authenticate(service === 'upload-pack' ? 'upload' : 'download', repoName, username, password, (error) => {
270-
if(error) {
271-
res.setHeader("Content-Type", 'text/plain');
272-
res.setHeader("WWW-Authenticate", 'Basic realm="authorization needed"');
273-
res.writeHead(401);
274-
res.end(error);
275-
return;
276-
} else {
277-
return infoResponse({
278-
repos: self,
279-
repo: repo,
280-
service: service,
281-
}, req, res);
282-
}
294+
var promise = this.authenticate(service === 'upload-pack' ? 'upload' : 'download', repoName, username, password, (error) => {
295+
return next(error);
283296
});
297+
if(promise instanceof Promise) {
298+
return promise
299+
.then(next)
300+
.catch(next);
301+
}
284302
});
285303
} else {
286-
return infoResponse({
287-
repos: self,
288-
repo: repo,
289-
service: service,
290-
}, req, res);
304+
return next();
291305
}
292306
},
293307
function(req, res) {

test/git.js

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ const async = require('async');
1010
const GitServer = require('../');
1111

1212
test('git', (t) => {
13-
t.plan(5);
13+
t.plan(6);
1414

1515
t.test('create, push to, and clone a repo', (t) => {
1616
var lastCommit;
@@ -666,5 +666,62 @@ test('git', (t) => {
666666

667667
});
668668

669+
t.test('should be able to protect certain routes with a promised authenticate', (t) => {
670+
const repoDir = `/tmp/${Math.floor(Math.random() * (1 << 30)).toString(16)}`;
671+
const srcDir = `/tmp/${Math.floor(Math.random() * (1 << 30)).toString(16)}`;
672+
const dstDir = `/tmp/${Math.floor(Math.random() * (1 << 30)).toString(16)}`;
673+
674+
fs.mkdirSync(repoDir, 0700);
675+
fs.mkdirSync(srcDir, 0700);
676+
fs.mkdirSync(dstDir, 0700);
677+
678+
const repos = new GitServer(repoDir, {
679+
autoCreate: true,
680+
authenticate: (type, repo, username, password) => {
681+
return new Promise(function(resolve, reject) {
682+
if(type == 'download', repo == 'doom' && username == 'root' && password == 'root') {
683+
return resolve();
684+
}
685+
return reject('that is not the correct password');
686+
});
687+
}
688+
});
689+
const port = Math.floor(Math.random() * ((1<<16) - 1e4)) + 1e4;
690+
repos.listen(port);
691+
692+
process.chdir(srcDir);
693+
async.waterfall([
694+
(callback) => {
695+
process.chdir(dstDir);
696+
const clone = spawn('git', [ 'clone', `http://root:root@localhost:${port}/doom.git` ]);
697+
698+
clone.on('close', function(code) {
699+
t.equal(code, 0);
700+
callback();
701+
});
702+
},
703+
(callback) => {
704+
process.chdir(dstDir);
705+
const clone = spawn('git', [ 'clone', `http://root:world@localhost:${port}/doom.git doom1` ]);
706+
let error = '';
707+
708+
clone.stderr.on('data', (d) => {
709+
error += d.toString('utf8');
710+
});
711+
712+
clone.on('close', function(code) {
713+
t.equal(error, `Cloning into 'doom.git doom1'...\nfatal: unable to access 'http://root:world@localhost:${port}/doom.git doom1/': Empty reply from server\n`);
714+
t.equal(code, 128);
715+
callback();
716+
});
717+
}
718+
], (err) => {
719+
t.ok(!err, 'no errors');
720+
repos.close();
721+
t.end();
722+
});
723+
724+
});
725+
669726
t.end();
670727
});

tryitout.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,4 @@ module.exports = {
4343
author: 'Made with ❤️ Gabriel J. Csapo',
4444
website: 'http://www.gabrielcsapo.com'
4545
}
46-
}
46+
};

0 commit comments

Comments
 (0)