mirror of
https://github.com/verdaccio/verdaccio.git
synced 2025-03-25 02:32:52 -05:00
Merge remote-tracking branch 'upstream/master'
Conflicts: lib/auth.js lib/index.js lib/middleware.js
This commit is contained in:
commit
6954898da0
41 changed files with 573 additions and 871 deletions
275
.eslint.yaml
275
.eslint.yaml
|
@ -1,275 +0,0 @@
|
|||
env:
|
||||
node: true
|
||||
|
||||
#
|
||||
# 0 - disable
|
||||
# Rules that more harmful than useful, or just buggy.
|
||||
#
|
||||
# 1 - warning
|
||||
# Rules that we didn't encounter yet. You can safely ignore them,
|
||||
# but I'd like to know any interesting use-cases they forbid.
|
||||
#
|
||||
# 2 - error
|
||||
# Rules that have proven to be useful, please follow them.
|
||||
#
|
||||
|
||||
rules:
|
||||
# didn't understand what it does, but it fails a good code
|
||||
block-scoped-var: 0
|
||||
|
||||
# fails where newlines are used to format pretty big "if":
|
||||
# if (
|
||||
# name.charAt(0) === "." ||
|
||||
# name.match(/[\/@\s\+%:]/) ||
|
||||
# name !== encodeURIComponent(name) ||
|
||||
# name.toLowerCase() === "node_modules"
|
||||
# ) {
|
||||
brace-style: 1
|
||||
|
||||
# snake_case is more readable, what's up with you guys?
|
||||
camelcase: 0
|
||||
|
||||
# if some functions are complex, they are for a good reason,
|
||||
# ain't worth it
|
||||
complexity: [0, 10]
|
||||
|
||||
# never saw it, but self is preferred
|
||||
consistent-this: [1, self]
|
||||
|
||||
# fails good code
|
||||
curly: [0, multi]
|
||||
|
||||
# fails good code, where this notation is used for consistency:
|
||||
# something['foo-bar'] = 123
|
||||
# something['blahblah'] = 234
|
||||
dot-notation: 0
|
||||
|
||||
# pointless in many cases (like indexOf() == -1), harmful in a few
|
||||
# cases (when you do want to ignore types), fails good code
|
||||
eqeqeq: 0
|
||||
|
||||
# if someone is changing prototype and makes properties enumerable,
|
||||
# it's their own fault
|
||||
guard-for-in: 0
|
||||
|
||||
# if some functions are complex, they are for a good reason,
|
||||
# ain't worth it
|
||||
max-depth: [0, 4]
|
||||
max-nested-callbacks: [0, 2]
|
||||
|
||||
# should it really throw for every long URL?
|
||||
max-len: [0, 80, 4]
|
||||
|
||||
# that's obvious by just looking at the code, you don't need lint for that
|
||||
max-params: [0, 3]
|
||||
|
||||
# if some functions are complex, they are for a good reason,
|
||||
# ain't worth it
|
||||
max-statements: [0, 10]
|
||||
|
||||
# that one makes sense
|
||||
new-cap: 2
|
||||
|
||||
# I'm writing javascript, not some weird reduced version of it
|
||||
no-bitwise: 0
|
||||
|
||||
# not working around IE bugs, sorry
|
||||
no-catch-shadow: 0
|
||||
|
||||
# see above, IE is useful for downloading other browsers only
|
||||
no-comma-dangle: 0
|
||||
|
||||
# good for removing debugging code
|
||||
no-console: 2
|
||||
|
||||
# good for removing debugging code
|
||||
no-debugger: 2
|
||||
|
||||
# why would anyone need to check against that?
|
||||
no-else-return: 0
|
||||
|
||||
# sometimes empty statement contains useful comment
|
||||
no-empty: 0
|
||||
|
||||
# stupid rule
|
||||
# "x == null" is "x === null || x === undefined"
|
||||
no-eq-null: 0
|
||||
|
||||
# fails good code, when parens are used for grouping:
|
||||
# (req && req.headers['via']) ? req.headers['via'] + ', ' : ''
|
||||
# not everyone remembers priority tables, you know
|
||||
no-extra-parens: 0
|
||||
|
||||
# fails defensive semicolons:
|
||||
# ;['foo', 'bar'].forEach(function(x) {})
|
||||
no-extra-semi: 0
|
||||
|
||||
# fails good code:
|
||||
# var fs = require('fs'),
|
||||
# , open = fs.open
|
||||
no-mixed-requires: [0, false]
|
||||
|
||||
# new Array(12) is used to pre-allocate arrays
|
||||
no-new-array: 0
|
||||
|
||||
# fails good code:
|
||||
# fs.open('/file', 0666, function(){})
|
||||
no-octal: 0
|
||||
|
||||
# fails good code:
|
||||
# console.log('\033[31m' + str + '\033[39m')
|
||||
# also fails \0 which is not octal escape
|
||||
no-octal-escape: 0
|
||||
|
||||
# I'm writing javascript, not some weird reduced version of it
|
||||
no-plusplus: 0
|
||||
|
||||
# fails good code:
|
||||
# if (a) {
|
||||
# var x = 'foo'
|
||||
# } else {
|
||||
# var x = bar
|
||||
# }
|
||||
no-redeclare: 0
|
||||
|
||||
# sometimes useful, often isn't
|
||||
# probably worth enforcing
|
||||
no-shadow: 2
|
||||
|
||||
no-sync: 2
|
||||
|
||||
# I'm writing javascript, not some weird reduced version of it
|
||||
no-ternary: 0
|
||||
|
||||
# the single most important rule in the entire ruleset
|
||||
no-undef: 2
|
||||
|
||||
# it is failing our own underscores
|
||||
no-underscore-dangle: 0
|
||||
|
||||
# fails function hoisting
|
||||
no-unreachable: 0
|
||||
|
||||
# fails npm-style code, it's good once you get used to it:
|
||||
# if (typeof(options) === 'function') callback = options, options = {}
|
||||
no-unused-expressions: 0
|
||||
|
||||
# fails (function(_err) {}) where named argument is used to show what
|
||||
# nth function argument means
|
||||
no-unused-vars: [0, local]
|
||||
|
||||
# fails function hoisting
|
||||
no-use-before-define: 0
|
||||
|
||||
# fails foobar( (function(){}).bind(this) )
|
||||
# parens are added for readability
|
||||
no-wrap-func: 0
|
||||
|
||||
# fails good code:
|
||||
# var x
|
||||
# if (something) {
|
||||
# var y
|
||||
one-var: 0
|
||||
|
||||
quote-props: 0
|
||||
|
||||
# fails situation when different quotes are used to avoid escaping
|
||||
quotes: [2, single, avoid-escape]
|
||||
|
||||
# http:#blog.izs.me/post/2353458699/an-open-letter-to-javascript-leaders-regarding
|
||||
semi: [2, never]
|
||||
|
||||
# fails good code where spaces are used for grouping:
|
||||
# (x+y * y+z)
|
||||
space-infix-ops: 0
|
||||
|
||||
# typeof(something) should have braces to look like a function
|
||||
# a matter of taste I suppose
|
||||
space-unary-word-ops: 0
|
||||
|
||||
# strict mode is just harmful,
|
||||
# can I have a check to enforce not using it?
|
||||
strict: 0
|
||||
|
||||
sort-vars: 0
|
||||
no-path-concat: 0
|
||||
func-names: 0
|
||||
|
||||
# how can you set a return code without process.exit?
|
||||
no-process-exit: 0
|
||||
|
||||
# both styles are useful
|
||||
func-style: [0, declaration]
|
||||
|
||||
# fails while(1) {...}
|
||||
no-constant-condition: 0
|
||||
|
||||
# fails good code:
|
||||
# https://github.com/rlidwka/jju/blob/eb52ee72e5f21d48963798f9bda8ac8d68082148/lib/parse.js#L732
|
||||
no-ex-assign: 0
|
||||
|
||||
wrap-iife: [2, inside]
|
||||
|
||||
# doesn't always make sense
|
||||
consistent-return: 0
|
||||
no-sequences: 0
|
||||
|
||||
# fails defensive semicolons
|
||||
no-space-before-semi: 0
|
||||
|
||||
new-parens: 1
|
||||
no-alert: 1
|
||||
no-array-constructor: 1
|
||||
no-caller: 1
|
||||
no-cond-assign: 1
|
||||
no-control-regex: 1
|
||||
no-delete-var: 1
|
||||
no-div-regex: 1
|
||||
no-dupe-keys: 1
|
||||
no-empty-class: 1
|
||||
no-empty-label: 1
|
||||
no-eval: 1
|
||||
no-extend-native: 1
|
||||
no-extra-boolean-cast: 1
|
||||
no-extra-strict: 1
|
||||
no-fallthrough: 1
|
||||
no-floating-decimal: 1
|
||||
no-func-assign: 1
|
||||
no-global-strict: 1
|
||||
no-implied-eval: 1
|
||||
no-invalid-regexp: 1
|
||||
no-iterator: 1
|
||||
no-labels: 1
|
||||
no-label-var: 1
|
||||
no-lone-blocks: 1
|
||||
no-loop-func: 1
|
||||
no-multi-str: 1
|
||||
no-native-reassign: 1
|
||||
no-negated-in-lhs: 1
|
||||
no-nested-ternary: 1
|
||||
no-new: 1
|
||||
no-new-func: 1
|
||||
no-new-object: 1
|
||||
no-new-wrappers: 1
|
||||
no-obj-calls: 1
|
||||
no-octal: 1
|
||||
no-proto: 1
|
||||
no-regex-spaces: 1
|
||||
no-return-assign: 1
|
||||
no-script-url: 1
|
||||
no-self-compare: 1
|
||||
no-shadow: 1
|
||||
no-shadow-restricted-names: 1
|
||||
no-spaced-func: 1
|
||||
no-sparse-arrays: 1
|
||||
no-sync: 1
|
||||
no-undef: 1
|
||||
no-undef-init: 1
|
||||
no-unreachable: 1
|
||||
no-with: 1
|
||||
no-yoda: 1
|
||||
radix: 1
|
||||
space-return-throw-case: 1
|
||||
use-isnan: 1
|
||||
valid-jsdoc: 1
|
||||
wrap-regex: 1
|
2
.eslintignore
Normal file
2
.eslintignore
Normal file
|
@ -0,0 +1,2 @@
|
|||
node_modules
|
||||
lib/static
|
44
.eslintrc
Normal file
44
.eslintrc
Normal file
|
@ -0,0 +1,44 @@
|
|||
# vim: syntax=yaml
|
||||
|
||||
#
|
||||
# List of very light restrictions designed to prevent obvious errors,
|
||||
# not impose our own code style upon other contributors.
|
||||
#
|
||||
# This is supposed to be used with `eslint --reset`
|
||||
#
|
||||
# Created to work with eslint@0.18.0
|
||||
#
|
||||
|
||||
env:
|
||||
node: true
|
||||
|
||||
rules:
|
||||
# useful to have in node.js,
|
||||
# if you're sure you don't need to handle error, rename it to "_err"
|
||||
handle-callback-err: 2
|
||||
|
||||
# just to make sure we don't forget to remove them when releasing
|
||||
no-debugger: 2
|
||||
|
||||
# add "falls through" for those
|
||||
no-fallthrough: 2
|
||||
|
||||
# just warnings about whitespace weirdness here
|
||||
eol-last: 1
|
||||
no-irregular-whitespace: 1
|
||||
no-mixed-spaces-and-tabs: [1, smart-tabs]
|
||||
no-trailing-spaces: 1
|
||||
|
||||
# probably always an error, tell me if it's not
|
||||
no-new-require: 2
|
||||
|
||||
# single most important rule here, without it linting won't even
|
||||
# make any sense
|
||||
no-undef: 2
|
||||
|
||||
# in practice, those are always errors
|
||||
no-unreachable: 2
|
||||
|
||||
# useful for code clean-up
|
||||
no-unused-vars: [1, {"vars": "all", "args": "none"}]
|
||||
|
|
@ -2,6 +2,8 @@ language: node_js
|
|||
node_js:
|
||||
- '0.10'
|
||||
- '0.12'
|
||||
- 'iojs-1.0'
|
||||
- 'iojs-1.6'
|
||||
- 'iojs'
|
||||
sudo: false
|
||||
script: npm install . && npm run test-travis
|
||||
|
|
13
History.md
13
History.md
|
@ -1,4 +1,14 @@
|
|||
|
||||
29 Mar 2015, version 1.1.0
|
||||
|
||||
- add a possibility to listen on multiple ports (issue [#172](https://github.com/rlidwka/sinopia/issues/172))
|
||||
- added https support (issues [#71](https://github.com/rlidwka/sinopia/issues/71), [#166](https://github.com/rlidwka/sinopia/issues/166))
|
||||
- added an option to use a custom template for web UI (issue [#208](https://github.com/rlidwka/sinopia/pull/208))
|
||||
- remove "from" and "resolved" fields from shrinkwrap (issue [#204](https://github.com/rlidwka/sinopia/issues/204))
|
||||
- fix hanging when rendering readme (issue [#206](https://github.com/rlidwka/sinopia/issues/206))
|
||||
- fix logger-related crash when using sinopia as a library
|
||||
- all requests to uplinks should now have proper headers
|
||||
|
||||
12 Feb 2015, version 1.0.1
|
||||
|
||||
- fixed issue with `max_users` option (issue [#184](https://github.com/rlidwka/sinopia/issues/184))
|
||||
|
@ -9,11 +19,12 @@
|
|||
|
||||
- switch markdown parser from `remarkable` to `markdown-it`
|
||||
- update `npm-shrinkwrap.json`
|
||||
- now downloading tarballs from upstream using the same protocol as for metadata (issue [#166](https://github.com/rlidwka/sinopia/issues/166))
|
||||
|
||||
22 Dec 2014, version 1.0.0-beta.2
|
||||
|
||||
- fix windows behavior when `$HOME` isn't set (issue [#177](https://github.com/rlidwka/sinopia/issues/177))
|
||||
- fix sanitization for highlighted code blocks in readme (issue [render-readme/#1](https://github.com/rlidwka/render-readme/issues/1)
|
||||
- fix sanitization for highlighted code blocks in readme (issue [render-readme/#1](https://github.com/rlidwka/render-readme/issues/1))
|
||||
|
||||
15 Dec 2014, version 1.0.0-beta
|
||||
|
||||
|
|
|
@ -40,9 +40,6 @@ $ sinopia
|
|||
# npm configuration
|
||||
$ npm set registry http://localhost:4873/
|
||||
|
||||
# if you have any restricted packages, you should add this:
|
||||
$ npm set always-auth true
|
||||
|
||||
# if you use HTTPS, add an appropriate CA information
|
||||
# ("null" means get CA list from OS)
|
||||
$ npm set ca null
|
||||
|
|
|
@ -19,6 +19,7 @@ web:
|
|||
|
||||
title: Sinopia
|
||||
# logo: logo.png
|
||||
# template: custom.hbs
|
||||
|
||||
auth:
|
||||
htpasswd:
|
||||
|
@ -84,8 +85,22 @@ packages:
|
|||
# if you use nginx with custom path, use this to override links
|
||||
#url_prefix: https://dev.company.local/sinopia/
|
||||
|
||||
# you can specify listen address (or simply a port)
|
||||
#listen: localhost:4873
|
||||
# You can specify listen address (or simply a port).
|
||||
# If you add multiple values, sinopia will listen on all of them.
|
||||
#
|
||||
# Examples:
|
||||
#
|
||||
#listen:
|
||||
# - localhost:4873 # default value
|
||||
# - http://localhost:4873 # same thing
|
||||
# - 0.0.0.0:4873 # listen on all addresses (INADDR_ANY)
|
||||
# - https://example.org:4873 # if you want to use https
|
||||
# - [::1]:4873 # ipv6
|
||||
|
||||
# Configure HTTPS, it is required if you use "https" protocol above.
|
||||
#https:
|
||||
# key: path/to/server.key
|
||||
# cert: path/to/server.crt
|
||||
|
||||
# type: file | stdout | stderr
|
||||
# level: trace | debug | info | http (default) | warn | error | fatal
|
||||
|
|
8
lib/GUI/.eslintrc
Normal file
8
lib/GUI/.eslintrc
Normal file
|
@ -0,0 +1,8 @@
|
|||
|
||||
env:
|
||||
node: true
|
||||
browser: true
|
||||
|
||||
globals:
|
||||
jQuery: true
|
||||
|
|
@ -27,8 +27,8 @@
|
|||
.npm-logo {
|
||||
width: 79px;
|
||||
height: @mainHeaderHeight;
|
||||
background-image: url( -/logo-sm );
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE8AAAAoCAYAAAC/xadkAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDozMDA4QUE4NzQ1QkMxMUU0QTVCMUYwQjdEREYxNENGMiIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDozMDA4QUE4ODQ1QkMxMUU0QTVCMUYwQjdEREYxNENGMiI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjMwMDhBQTg1NDVCQzExRTRBNUIxRjBCN0RERjE0Q0YyIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjMwMDhBQTg2NDVCQzExRTRBNUIxRjBCN0RERjE0Q0YyIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+ypkYZgAACelJREFUeNrsWmts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);
|
||||
// https://example.org/sinopia/-/static/../../-/logo
|
||||
background-image: url( ../../-/logo );
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
var $ = require('unopinionate').selector
|
||||
var template = require('../entry.hbs')
|
||||
var onScroll = require('onscroll')
|
||||
|
||||
$(function() {
|
||||
;(function(window, document) {
|
||||
var $form = $('#search-form')
|
||||
var $input = $form.find('input')
|
||||
var $body = $('body')
|
||||
var $clear = $form.find('.clear')
|
||||
var $searchResults = $('#search-results')
|
||||
var $pkgListing = $('#all-packages')
|
||||
var $searchBtn = $('.js-search-btn')
|
||||
|
|
|
@ -158,7 +158,7 @@ Auth.prototype.bearer_middleware = function() {
|
|||
var self = this
|
||||
return function(req, res, _next) {
|
||||
req.pause()
|
||||
function next(err) {
|
||||
function next(_err) {
|
||||
req.resume()
|
||||
return _next.apply(null, arguments)
|
||||
}
|
||||
|
@ -197,7 +197,7 @@ Auth.prototype.cookie_middleware = function() {
|
|||
var self = this
|
||||
return function(req, res, _next) {
|
||||
req.pause()
|
||||
function next(err) {
|
||||
function next(_err) {
|
||||
req.resume()
|
||||
return _next()
|
||||
}
|
||||
|
|
113
lib/cli.js
113
lib/cli.js
|
@ -19,10 +19,15 @@ var logger = require('./logger')
|
|||
logger.setup() // default setup
|
||||
|
||||
var commander = require('commander')
|
||||
var constants = require('constants')
|
||||
var fs = require('fs')
|
||||
var http = require('http')
|
||||
var https = require('https')
|
||||
var YAML = require('js-yaml')
|
||||
var Path = require('path')
|
||||
var URL = require('url')
|
||||
var server = require('./index')
|
||||
var Utils = require('./utils')
|
||||
var pkg_file = '../package.yaml'
|
||||
var pkg = YAML.safeLoad(fs.readFileSync(__dirname+'/'+ pkg_file, 'utf8'))
|
||||
|
||||
|
@ -41,7 +46,7 @@ if (commander.args.length != 0) {
|
|||
commander.help()
|
||||
}
|
||||
|
||||
var config, config_path, have_question
|
||||
var config, config_path
|
||||
try {
|
||||
if (commander.config) {
|
||||
config_path = Path.resolve(commander.config)
|
||||
|
@ -57,36 +62,106 @@ try {
|
|||
|
||||
afterConfigLoad()
|
||||
|
||||
function get_hostport() {
|
||||
function get_listen_addresses() {
|
||||
// command line || config file || default
|
||||
var hostport = commander.listen || String(config.listen || '') || '4873'
|
||||
var addresses
|
||||
|
||||
hostport = hostport.split(':')
|
||||
if (hostport.length < 2) {
|
||||
hostport = [ undefined, hostport[0] ]
|
||||
if (commander.listen) {
|
||||
addresses = [ commander.listen ]
|
||||
} else if (Array.isArray(config.listen)) {
|
||||
addresses = config.listen
|
||||
} else if (config.listen) {
|
||||
addresses = [ config.listen ]
|
||||
} else {
|
||||
addresses = [ '4873' ]
|
||||
}
|
||||
if (hostport[0] == null) {
|
||||
hostport[0] = 'localhost'
|
||||
}
|
||||
return hostport
|
||||
|
||||
addresses = addresses.map(function(addr) {
|
||||
addr = Utils.parse_address(addr)
|
||||
|
||||
if (!addr) {
|
||||
logger.logger.warn({ addr: addr },
|
||||
'invalid address - @{addr}, we expect a port (e.g. "4873"),'
|
||||
+ ' host:port (e.g. "localhost:4873") or full url'
|
||||
+ ' (e.g. "http://localhost:4873/")')
|
||||
}
|
||||
|
||||
return addr
|
||||
|
||||
}).filter(Boolean)
|
||||
|
||||
return addresses
|
||||
}
|
||||
|
||||
function afterConfigLoad() {
|
||||
if (!config.self_path) config.self_path = Path.resolve(config_path)
|
||||
if (!config.https) config.https = { enable: false };
|
||||
|
||||
var hostport = get_hostport()
|
||||
server(config)
|
||||
.listen(hostport[1], hostport[0])
|
||||
.on('error', function(err) {
|
||||
logger.logger.fatal({ err: err }, 'cannot create server: @{err.message}')
|
||||
process.exit(2)
|
||||
})
|
||||
var app = server(config)
|
||||
|
||||
logger.logger.warn({ addr: 'http://'+hostport[0]+':'+hostport[1]+'/', version: 'Sinopia/'+pkg.version }, 'http address - @{addr}')
|
||||
get_listen_addresses().forEach(function(addr) {
|
||||
var webServer
|
||||
|
||||
if (addr.proto === 'https') { // https
|
||||
if (!config.https || !config.https.key || !config.https.cert) {
|
||||
var conf_path = function(file) {
|
||||
if (!file) return config_path
|
||||
return Path.resolve(Path.dirname(config_path), file)
|
||||
}
|
||||
|
||||
logger.logger.fatal([
|
||||
'You need to specify "https.key" and "https.cert" to run https server',
|
||||
'',
|
||||
// commands are borrowed from node.js docs
|
||||
'To quickly create self-signed certificate, use:',
|
||||
' $ openssl genrsa -out ' + conf_path('sinopia-key.pem') + ' 2048',
|
||||
' $ openssl req -new -sha256 -key ' + conf_path('sinopia-key.pem') + ' -out ' + conf_path('sinopia-csr.pem'),
|
||||
' $ openssl x509 -req -in ' + conf_path('sinopia-csr.pem') + ' -signkey ' + conf_path('sinopia-key.pem') + ' -out ' + conf_path('sinopia-cert.pem'),
|
||||
'',
|
||||
'And then add to config file (' + conf_path() + '):',
|
||||
' https:',
|
||||
' key: sinopia-key.pem',
|
||||
' cert: sinopia-cert.pem',
|
||||
].join('\n'))
|
||||
process.exit(2)
|
||||
}
|
||||
|
||||
try {
|
||||
webServer = https.createServer({
|
||||
secureProtocol: 'SSLv23_method', // disable insecure SSLv2 and SSLv3
|
||||
secureOptions: constants.SSL_OP_NO_SSLv2 | constants.SSL_OP_NO_SSLv3,
|
||||
key: fs.readFileSync(config.https.key),
|
||||
cert: fs.readFileSync(config.https.cert)
|
||||
}, app)
|
||||
} catch (err) { // catch errors related to certificate loading
|
||||
logger.logger.fatal({ err: err }, 'cannot create server: @{err.message}')
|
||||
process.exit(2)
|
||||
}
|
||||
} else { // http
|
||||
webServer = http.createServer(app);
|
||||
}
|
||||
|
||||
webServer
|
||||
.listen(addr.port, addr.host)
|
||||
.on('error', function(err) {
|
||||
logger.logger.fatal({ err: err }, 'cannot create server: @{err.message}')
|
||||
process.exit(2)
|
||||
})
|
||||
|
||||
logger.logger.warn({
|
||||
addr: URL.format({
|
||||
protocol: addr.proto,
|
||||
hostname: addr.host,
|
||||
port: addr.port,
|
||||
pathname: '/',
|
||||
}),
|
||||
version: 'Sinopia/'+pkg.version,
|
||||
}, 'http address - @{addr}')
|
||||
})
|
||||
|
||||
// undocumented stuff for tests
|
||||
if (typeof(process.send) === 'function') {
|
||||
process.send({ sinopia_started: hostport })
|
||||
process.send({ sinopia_started: true })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@ var Cookies = require('cookies')
|
|||
var express = require('express')
|
||||
var fs = require('fs')
|
||||
var Handlebars = require('handlebars')
|
||||
var Error = require('http-errors')
|
||||
var renderReadme = require('render-readme')
|
||||
var async = require('async')
|
||||
var Search = require('./search')
|
||||
|
@ -34,11 +33,17 @@ module.exports = function(config, auth, storage, package_provider) {
|
|||
|
||||
Search.configureStorage(storage)
|
||||
|
||||
Handlebars.registerPartial('entry', fs.readFileSync(require.resolve('./GUI/entry.hbs'), 'utf8'))
|
||||
var template = Handlebars.compile(fs.readFileSync(require.resolve('./GUI/index.hbs'), 'utf8'))
|
||||
|
||||
if(config.web && config.web.template) {
|
||||
var template = Handlebars.compile(fs.readFileSync(config.web.template, 'utf8'));
|
||||
}
|
||||
else {
|
||||
Handlebars.registerPartial('entry', fs.readFileSync(require.resolve('./GUI/entry.hbs'), 'utf8'))
|
||||
var template = Handlebars.compile(fs.readFileSync(require.resolve('./GUI/index.hbs'), 'utf8'))
|
||||
}
|
||||
app.get('/', function(req, res, next) {
|
||||
var base = config.url_prefix || req.protocol + '://' + req.get('host')
|
||||
var base = config.url_prefix
|
||||
? config.url_prefix.replace(/\/$/, '')
|
||||
: req.protocol + '://' + req.get('host')
|
||||
res.setHeader('Content-Type', 'text/html')
|
||||
|
||||
storage.get_local(function(err, packages) {
|
||||
|
@ -73,11 +78,9 @@ module.exports = function(config, auth, storage, package_provider) {
|
|||
})
|
||||
|
||||
app.get('/-/logo', function(req, res, next) {
|
||||
res.sendFile(config.web.logo ? config.web.logo : __dirname + '/static/logo.png')
|
||||
})
|
||||
|
||||
app.get('/-/logo-sm', function(req, res, next) {
|
||||
res.sendFile(config.web.logosm ? config.web.logosm : __dirname + '/static/logo-sm.png')
|
||||
res.sendFile( config.web && config.web.logo
|
||||
? config.web.logo
|
||||
: __dirname + '/static/logo-sm.png' )
|
||||
})
|
||||
|
||||
app.post('/-/login', function(req, res, next) {
|
||||
|
@ -90,13 +93,17 @@ module.exports = function(config, auth, storage, package_provider) {
|
|||
res.cookies.set('token', auth.aes_encrypt(str).toString('base64'))
|
||||
}
|
||||
|
||||
var base = config.url_prefix || req.protocol + '://' + req.get('host')
|
||||
var base = config.url_prefix
|
||||
? config.url_prefix.replace(/\/$/, '')
|
||||
: req.protocol + '://' + req.get('host')
|
||||
res.redirect(base)
|
||||
})
|
||||
})
|
||||
|
||||
app.post('/-/logout', function(req, res, next) {
|
||||
var base = config.url_prefix || req.protocol + '://' + req.get('host')
|
||||
var base = config.url_prefix
|
||||
? config.url_prefix.replace(/\/$/, '')
|
||||
: req.protocol + '://' + req.get('host')
|
||||
res.cookies.set('token', '')
|
||||
res.redirect(base)
|
||||
})
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
var express = require('express')
|
||||
var fs = require('fs')
|
||||
var Error = require('http-errors')
|
||||
var compression = require('compression')
|
||||
var Auth = require('./auth')
|
||||
|
@ -18,7 +17,6 @@ module.exports = function(config_hash) {
|
|||
var auth = Auth(config)
|
||||
var packages = PackageProvider(config)
|
||||
var app = express()
|
||||
var can = Middleware.allow(config, packages)
|
||||
|
||||
// run in production mode by default, just in case
|
||||
// it shouldn't make any difference anyway
|
||||
|
|
|
@ -26,7 +26,7 @@ LocalData.prototype.remove = function(name) {
|
|||
if (i !== -1) {
|
||||
this.data.list.splice(i, 1)
|
||||
}
|
||||
|
||||
|
||||
this.sync()
|
||||
}
|
||||
|
||||
|
|
|
@ -44,7 +44,6 @@ Storage.prototype._internal_error = function(err, file, message) {
|
|||
}
|
||||
|
||||
Storage.prototype.add_package = function(name, info, callback) {
|
||||
var self = this
|
||||
var storage = this.storage(name)
|
||||
if (!storage) return callback( Error[404]('this package cannot be added') )
|
||||
|
||||
|
@ -101,7 +100,7 @@ Storage.prototype.remove_package = function(name, callback) {
|
|||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
Search.remove(name)
|
||||
this.config.localList.remove(name)
|
||||
}
|
||||
|
@ -267,11 +266,6 @@ Storage.prototype.add_tags = function(name, tags, callback) {
|
|||
}, callback)
|
||||
}
|
||||
|
||||
// change package info to tag a specific version
|
||||
function _add_tag(data, version, tag) {
|
||||
data['dist-tags'][tag] = version
|
||||
}
|
||||
|
||||
// currently supports unpublishing only
|
||||
Storage.prototype.change_package = function(name, metadata, revision, callback) {
|
||||
var self = this
|
||||
|
|
|
@ -95,8 +95,7 @@ module.exports.allow = function(config, packages) {
|
|||
}
|
||||
next( Error[403](message) )
|
||||
} else {
|
||||
next( Error[403]('user ' + req.remote_user.name
|
||||
+ ' not allowed to ' + action + ' it') )
|
||||
var message = "can't "+action+" restricted package, you are not logged in"
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -154,7 +153,6 @@ module.exports.log = function(req, res, next) {
|
|||
var _cookie = req.headers.cookie
|
||||
if (_cookie != null) req.headers.cookie = '<Classified>'
|
||||
|
||||
var _url = req.url
|
||||
req.url = req.originalUrl
|
||||
req.log.info( { req: req, ip: req.ip }
|
||||
, '@{ip} requested \'@{req.method} @{req.url}\'' )
|
||||
|
@ -183,7 +181,6 @@ module.exports.log = function(req, res, next) {
|
|||
message += ', bytes: @{bytes.in}/@{bytes.out}'
|
||||
}
|
||||
|
||||
var _url = req.url
|
||||
req.url = req.originalUrl
|
||||
req.log.warn({
|
||||
request : { method: req.method, url: req.url },
|
||||
|
|
|
@ -7241,8 +7241,7 @@ Original style from softwaremaniacs.org (c) Ivan Sagalaev <Maniac@SoftwareManiac
|
|||
.body .main-header .npm-logo {
|
||||
width: 79px;
|
||||
height: 50px;
|
||||
background-image: url(-/logo-sm );
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE8AAAAoCAYAAAC/xadkAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDozMDA4QUE4NzQ1QkMxMUU0QTVCMUYwQjdEREYxNENGMiIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDozMDA4QUE4ODQ1QkMxMUU0QTVCMUYwQjdEREYxNENGMiI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjMwMDhBQTg1NDVCQzExRTRBNUIxRjBCN0RERjE0Q0YyIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjMwMDhBQTg2NDVCQzExRTRBNUIxRjBCN0RERjE0Q0YyIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+ypkYZgAACelJREFUeNrsWmtsHFcZPXd2Zh9+r+31+5W4tSPSoKZUKgpIgdAWqorSULVFqJREKpVAAqRKhfIPKfCDtP2TKilpRRACUpBC+UlbQRG0RUmo0gBtWoyT2HHstR0/Yq/X9j5mh/PdmfX7te42tZyMdO2dmTt3vnvu+Z53lHOm9VcwQntRuvMq0qMKmTSgDNw4Fh4OG3Gxyh3E/l2GZOxVE0UtDShqLUbCLkb9o0D6KmAnbgA4D7cMcbMIXAUw+BoQ2QXEu5pMAjqB2q8Cl34BXDwC1D3IzkkgNUEAfTeAE+B8IWJhAl0vAKECoOa7wIVDEwbsaQUMA03fAMJbgJ5fAxlS1Crjg/Z1DhznbxbzB1l3+SWguBpo2cdzamd6wjBcdqXYeoHa+8m8T/PncSBJ5gUiHCB9nQLHefvLCRK1sPe3QNUtQAO1ElE2MWumcJHEg881iE43ULGbQIdJ0RNA5V1EuxWY7r++VFiAC5JlcRLqyp+olV8CSm938RGn4foDwyR2xowzcQy3Q8l24KYi6vVviHyc6ryTAPa5OLt/Nq9HddiCddTM94GxvwFbHwIKb6YpE+CEa9n5K2HewoOXMj1AAQfY9h2g8xi1mjpevYdATnoob+JQxEeHcOUNauYHQNtjVN0KFw8sgEppFyJQLmQTDWRmgP3LXQDPU+ejpK+/lNeTm5R9jlZEpEgQRbJse5z//ZxvdDFw7mHM5eHCe2wxtnqglfHfMEOZcJt7eVOyjzA4hGP0TaD8EZ7TWeKC5w+WfsBc1o7xVvpqCom+Dhi+KWCSIMbb+QLxzJnNCZ6iyo50w4l2kHRjCDYTHstw7eDi/ssxj51VGMOvnsK5b55Awc0RbwXObn6HQVW1Y2/DoMbu/PN+BBoreTm21LxJL0MtO5AiroKvMg0XY8fa/GGKIZ7AdCMzzatltEwJMkl4DsNZDJ7PoPOxYIQs/vZhuqsL9tRkbuwj5YNNTfCVlOhUJzM1hamLXbnPyW8huGWr+9uykIj2ITU8nD9NoJxmaSlVtYmWyeY71GpDk3mJtLGMN5kTM6ZJ5Rgan3gCwYZGYrB2m6eYxPQfP474++f072BjI5p/8EPK6qzZ78hzqZER9L34ol7U6YEBRO67D6W7djGDyo/9lXfE33sX/S8d50IVr7IoyrN5RSZ/rZLD2jbsiQlUP/wwAnX1OQs2+vpfMPbWmxTKD5MMrHrwodyJkUrj8pHDWuzk4ABKP/NZVD3wQF41dowL2/PcIQRqi9eGNxy1Ou/F9lFtk/396xIqk0jQa1nalgiL13Mk+nq9kJQpkeVnJHA17+ZOzIDi2Gu0BBKq5KdwlxocRCaVdGPNUAhWRcU6ihhpjnNF2x+HbDc5hq+gIOdx7PExpMfHKYihF91fVT0TVNjxONI0AbKQ8h4rEtELm7tXltGh8mJxz+3fh7fvuAOnb7sVnU8+uT52RaN454t348wX9uDUJ3dg+JVX1jVOz+HDOLnjFpzZvRv/2bsX9uTkzL0rf3wZJ7d/Au/cfRfO7Pk8ndfFnB2LDttsnZ7lx12Jatr0pPI/k0yuz2hnHGSmp8nglDthe30qLqYhMzkFm2NJmxvkZsT5UU5p2oQ4OWZLKpvKubltXmpNvqIi7eoFPF9haJ0xlqEdioCXIXi5q5M3TCCgZZGxfMXF85RLO62yMn1PwBMvmzt6oraGtnf5CZQcZ07L0zj4iMbJ0zuMDZdtCROyplht5FRQ6eh4w5SIxcMm6TREbRP0umK3Nmbdb149b4OsJW1cQVubdjhmRaW2WxuYefnztvk4AnV12Pn6X+es8Mau4Bj5CpI/kvragixnxfNVMqS8jLPYOq++vI4X8ftr61bIVdzUy6G9MoLzQxUjGOT15IciUqC+fsZDarWWKs1yYZOEIZRDZJay2twsxSoLu3GoNydhe/bwM9tw1hSjuhMx4RXWV07iTJjFJeh9/oiehBQJsgNI+qMsE+mxMZjhsBZoqqsLvUd/rstPkqolenrgr65m2hRb8T2Sr/a+cJTBcQYq4PdsswODk0+PjupSlDAl2FCvs4/U8NA8Wdx4sxDjb/2DC12r3y0LeumZpxn7BaH8FibOnkWQgIl9NcidS88+C7OyQsd7kx0d8NdUr4GNTtbmqZULV1IUMH0wykrR98tjFDYOwzTnsVLqdKGtrTr4FCESPd3ofOop9vNpMIPNzbAqIwR4fOX8mAB1HTigmSHsUToY5d+0rQPfUOtWLbevphZjb/wdg384MU+WbHYhwAkI8pycdx88qOWQUpq/shKBhgaXYYbCZRIi42UhIn9wSzMXZWIVAGeZt+wGUCbBRH1oElZVmGy4CrOonG3phN+OJXTLGvpATZM3G7LICripltQBVzCxFoUvaG/XoYrJxbLH4pxYcuaZ1FDMW3epcgdm37EoV3QY8swWSq2K2nkBciI6JJGGC0BpBCidZVQyOoJ03A+fOe3VLdVypFKzm96LeQCjKIRASx38RYNAMAJd2HcyOdt8J5FhTikfzJCJUk2WVRcm2PbMhBSZJQVPPb7YowQBLAkC4dA13KwTKNLwDfXAKG+nxgX1+fIlKdub4jwBZVIZVH55B8q3n2KHTwF1j7J7LDfwZD/AF8EHj/+MNuo0gi31SA0M6IqGZuHc9Mhwd6mUPwAf29T5KNqf/x4iX7mTxj96bcIWzXA6m77fQzlnYNSUecDEMb/a7ngZhiPfWBhz0CPSRg3/jUJ1H4WvSr5X2SfFHLaCHCchfUvd2hnBEhsorEsP9Hs2Zc5Y+hs4n1ZXfZ2q5yukkTfl+YlrFPM5btv6feL1O+B/zwHNj9DV1y7e/NYZhiXbZxmvWCDANQOxd4Gel4EIQSu+nzc6PPoa61CDKUxdGMDEQI/+YkvbkRWMcbJ/Qv+Pj/QgOTCqnweuFXhZAOnYCr8GlNO+d9L7N95DQt7GW5e8OSlPbXUZ3puQ2gIMvwZET/OBH5M0O9jnPS/9XW8KPIb6b9+J8J52WOFi1zuvpTI9EkPJ7S3Q38LhWsbx2Z1Ezrvyc7T1jUD3AaCK2hK5l7f6kN2OVE7nPf9F67fa9Nnl41xk2rUtBC4gmyBdEjp+SGGEsYydUAj3O8C1MkhqeYMuC/Bx7RdLwEzwJMC/8BMgRNmbvi4hO6E51mXCX8Yr9CqdT7sdt/3UEzgfwGWjoSGvrYcFH+dGu8z/snzEDbQ/QwAP0g4eAm76ERUxrJRz/t4hFLVUwLqVYcF+dpbv0CaxeC93qUTdWUD1jVQ2Ujn0XS2/TrtsA4P0UWpn4qR8rzhuYvRfHUhNtaG8OoZLjyk3FDFmH1ZzQpn5HwWpZZP42WtqWaHUjOxqaQeiVkv21Rr7L86gFoumlh5j7nnGRSLY5iDeX4jRf3b9X4ABADgctRMdEJWtAAAAAElFTkSuQmCC);
|
||||
background-image: url(../../-/logo );
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
}
|
||||
|
|
|
@ -373,7 +373,7 @@ $(function() {
|
|||
})
|
||||
})
|
||||
|
||||
},{"onclick":13,"transition-complete":15,"unopinionate":16}],4:[function(require,module,exports){
|
||||
},{"onclick":13,"transition-complete":14,"unopinionate":15}],4:[function(require,module,exports){
|
||||
// twitter bootstrap stuff;
|
||||
// not in static 'cause I want it to be bundled with the rest of javascripts
|
||||
require('./bootstrap-modal')
|
||||
|
@ -388,17 +388,14 @@ $(document).on('click', '.js-userLogoutBtn', function() {
|
|||
return false
|
||||
})
|
||||
|
||||
},{"./bootstrap-modal":2,"./entry":3,"./search":5,"unopinionate":16}],5:[function(require,module,exports){
|
||||
},{"./bootstrap-modal":2,"./entry":3,"./search":5,"unopinionate":15}],5:[function(require,module,exports){
|
||||
var $ = require('unopinionate').selector
|
||||
var template = require('../entry.hbs')
|
||||
var onScroll = require('onscroll')
|
||||
|
||||
$(function() {
|
||||
;(function(window, document) {
|
||||
var $form = $('#search-form')
|
||||
var $input = $form.find('input')
|
||||
var $body = $('body')
|
||||
var $clear = $form.find('.clear')
|
||||
var $searchResults = $('#search-results')
|
||||
var $pkgListing = $('#all-packages')
|
||||
var $searchBtn = $('.js-search-btn')
|
||||
|
@ -469,7 +466,7 @@ $(function() {
|
|||
})(window, window.document)
|
||||
})
|
||||
|
||||
},{"../entry.hbs":1,"onscroll":14,"unopinionate":16}],6:[function(require,module,exports){
|
||||
},{"../entry.hbs":1,"unopinionate":15}],6:[function(require,module,exports){
|
||||
"use strict";
|
||||
/*globals Handlebars: true */
|
||||
var base = require("./handlebars/base");
|
||||
|
@ -1231,30 +1228,7 @@ $(document).bind('mousedown', click._doAnywheres);
|
|||
module.exports = click;
|
||||
|
||||
|
||||
},{"unopinionate":16}],14:[function(require,module,exports){
|
||||
var $ = require('unopinionate').selector;
|
||||
|
||||
var bodyScrollers = [];
|
||||
|
||||
$(function() {
|
||||
var $html = $('html'),
|
||||
$body = $('body');
|
||||
|
||||
$(window, document, 'body').bind('scroll touchmove', function() {
|
||||
var top = $html[0].scrollTop || $body[0].scrollTop;
|
||||
|
||||
for(var i=0; i<bodyScrollers.length; i++) {
|
||||
bodyScrollers[i](top);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
var onScroll = function(callback) {
|
||||
bodyScrollers.push(callback);
|
||||
};
|
||||
|
||||
module.exports = onScroll;
|
||||
},{"unopinionate":16}],15:[function(require,module,exports){
|
||||
},{"unopinionate":15}],14:[function(require,module,exports){
|
||||
(function(root) {
|
||||
var callbacks = [];
|
||||
|
||||
|
@ -1318,7 +1292,7 @@ module.exports = onScroll;
|
|||
}
|
||||
})(this);
|
||||
|
||||
},{}],16:[function(require,module,exports){
|
||||
},{}],15:[function(require,module,exports){
|
||||
(function (global){
|
||||
(function(root) {
|
||||
var unopinionate = {
|
||||
|
|
|
@ -190,7 +190,6 @@ Storage.prototype.get_tarball = function(name, filename) {
|
|||
|
||||
// local reported 404
|
||||
var err404 = err
|
||||
var uplink = null
|
||||
rstream.abort()
|
||||
rstream = null // gc
|
||||
|
||||
|
@ -386,9 +385,10 @@ Storage.prototype.search = function(startkey, options, callback) {
|
|||
return merge_with_local_packages(null, null, {})
|
||||
}
|
||||
self.uplinks[uplinks[i]].request({
|
||||
uri: options.req.url,
|
||||
timeout: self.uplinks[p].timeout,
|
||||
json: true,
|
||||
uri : options.req.url,
|
||||
timeout : self.uplinks[p].timeout,
|
||||
json : true,
|
||||
req : options.req,
|
||||
}, function(err, res, body) {
|
||||
if (err || Math.floor(res.statusCode / 100) > 3) {
|
||||
i++
|
||||
|
|
|
@ -111,6 +111,7 @@ Storage.prototype.request = function(options, cb) {
|
|||
headers['Accept'] = headers['Accept'] || 'application/json'
|
||||
headers['Accept-Encoding'] = headers['Accept-Encoding'] || 'gzip'
|
||||
headers['User-Agent'] = headers['User-Agent'] || this.userAgent
|
||||
this._add_proxy_headers(options.req, headers)
|
||||
|
||||
var method = options.method || 'GET'
|
||||
var uri = options.uri_full || (this.config.url + options.uri)
|
||||
|
@ -253,12 +254,12 @@ Storage.prototype.get_package = function(name, options, callback) {
|
|||
headers['If-None-Match'] = options.etag
|
||||
headers['Accept'] = 'application/octet-stream'
|
||||
}
|
||||
this._add_proxy_headers(options.req, headers)
|
||||
|
||||
this.request({
|
||||
uri : '/' + encode(name),
|
||||
json : true,
|
||||
headers : headers,
|
||||
req : options.req,
|
||||
}, function(err, res, body) {
|
||||
if (err) return callback(err)
|
||||
if (res.statusCode === 404) {
|
||||
|
|
23
lib/utils.js
23
lib/utils.js
|
@ -122,6 +122,29 @@ module.exports.get_version = function(object, version) {
|
|||
}
|
||||
}
|
||||
|
||||
module.exports.parse_address = function parse_address(addr) {
|
||||
//
|
||||
// Allow:
|
||||
//
|
||||
// - https:localhost:1234 - protocol + host + port
|
||||
// - localhost:1234 - host + port
|
||||
// - 1234 - port
|
||||
// - http::1234 - protocol + port
|
||||
// - https://localhost:443/ - full url + https
|
||||
// - http://[::1]:443/ - ipv6
|
||||
//
|
||||
// protocol : // ( host )|( ipv6 ): port /
|
||||
var m = /^((https?):(\/\/)?)?((([^\/:]*)|\[([^\[\]]+)\]):)?(\d+)\/?$/.exec(addr)
|
||||
|
||||
if (!m) return null
|
||||
|
||||
return {
|
||||
proto: m[2] || 'http',
|
||||
host: m[6] || m[7] || 'localhost',
|
||||
port: m[8] || '4873',
|
||||
}
|
||||
}
|
||||
|
||||
// function filters out bad semver versions and sorts the array
|
||||
module.exports.semver_sort = function semver_sort(array) {
|
||||
return array
|
||||
|
|
694
npm-shrinkwrap.json
generated
694
npm-shrinkwrap.json
generated
File diff suppressed because it is too large
Load diff
31
package.yaml
31
package.yaml
|
@ -1,7 +1,7 @@
|
|||
# use "yapm install ." if you're installing this from git repository
|
||||
|
||||
name: sinopia
|
||||
version: 1.0.1
|
||||
version: 1.1.0
|
||||
description: Private npm repository server
|
||||
|
||||
author:
|
||||
|
@ -55,12 +55,14 @@ devDependencies:
|
|||
# Tools required for testing
|
||||
#
|
||||
rimraf: '>=2.2.5 <3.0.0-0'
|
||||
mocha: '>=1.17.0 <2.0.0-0'
|
||||
|
||||
# https://github.com/mochajs/mocha/issues/1614
|
||||
mocha: '<= 1.20'
|
||||
|
||||
#
|
||||
# Linting tools
|
||||
#
|
||||
eslint: '~0.6.0'
|
||||
eslint: '>= 0.18'
|
||||
|
||||
# for debugging memory leaks, it'll be require()'d if
|
||||
# installed, but I don't want it to be installed everytime
|
||||
|
@ -81,7 +83,6 @@ devDependencies:
|
|||
# not required in runtime
|
||||
unopinionate: '>=0.0.4 <1.0.0-0'
|
||||
onclick: '>=0.1.0 <1.0.0-0'
|
||||
onscroll: '>=0.0.3 <1.0.0-0'
|
||||
transition-complete: '>=0.0.2 <1.0.0-0'
|
||||
|
||||
keywords:
|
||||
|
@ -94,10 +95,26 @@ keywords:
|
|||
- server
|
||||
|
||||
scripts:
|
||||
test: mocha -R dot ./test/functional ./test/unit
|
||||
test-travis: mocha -R spec ./test/functional ./test/unit
|
||||
lint: eslint -c ./.eslint.yaml ./lib
|
||||
test: eslint --reset . && mocha -R dot ./test/functional ./test/unit
|
||||
test-travis: eslint --reset . && mocha -R spec ./test/functional ./test/unit
|
||||
test-only: mocha -R dot ./test/functional ./test/unit
|
||||
lint: eslint --reset .
|
||||
prepublish: js-yaml package.yaml > package.json
|
||||
clean-shrinkwrap: |
|
||||
node -e '
|
||||
function clean(j) {
|
||||
if (!j) return
|
||||
for (var k in j) {
|
||||
delete j[k].from
|
||||
delete j[k].resolved
|
||||
if (j[k].dependencies) clean(j[k].dependencies)
|
||||
}
|
||||
}
|
||||
x = JSON.parse(require("fs").readFileSync("./npm-shrinkwrap.json"))
|
||||
clean(x.dependencies)
|
||||
x = JSON.stringify(x, null, " ")
|
||||
require("fs").writeFileSync("./npm-shrinkwrap.json", x + "\n")
|
||||
'
|
||||
|
||||
# we depend on streams2 stuff
|
||||
# it can be replaced with isaacs/readable-stream, ask if you need to use 0.8
|
||||
|
|
5
test/.eslintrc
Normal file
5
test/.eslintrc
Normal file
|
@ -0,0 +1,5 @@
|
|||
|
||||
env:
|
||||
node: true
|
||||
mocha: true
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
require('./lib/startup')
|
||||
|
||||
var assert = require('assert')
|
||||
var async = require('async')
|
||||
var crypto = require('crypto')
|
||||
|
||||
function readfile(x) {
|
||||
|
@ -132,6 +131,7 @@ module.exports = function() {
|
|||
|
||||
it('who am I?', function(cb) {
|
||||
server.request({uri:'/-/whoami'}, function(err, res, body) {
|
||||
assert.equal(err, null)
|
||||
assert.equal(res.statusCode, 200)
|
||||
assert.equal(body.username, 'test')
|
||||
cb()
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
require('./lib/startup')
|
||||
|
||||
var assert = require('assert')
|
||||
var async = require('async')
|
||||
var crypto = require('crypto')
|
||||
|
||||
function readfile(x) {
|
||||
return require('fs').readFileSync(__dirname + '/' + x)
|
||||
|
@ -34,7 +32,7 @@ module.exports = function() {
|
|||
x.versions['0.0.9'] = x.versions['0.0.1']
|
||||
|
||||
require('zlib').gzip(JSON.stringify(x), function(err, buf) {
|
||||
assert(!err)
|
||||
assert.equal(err, null)
|
||||
assert.equal(req.headers['accept-encoding'], 'gzip')
|
||||
res.header('content-encoding', 'gzip')
|
||||
res.send(buf)
|
||||
|
@ -74,13 +72,14 @@ module.exports = function() {
|
|||
},
|
||||
json: false,
|
||||
}, function(err, res, body) {
|
||||
assert.equal(err, null)
|
||||
assert.equal(res.statusCode, 200)
|
||||
assert.equal(res.headers['content-encoding'], 'gzip')
|
||||
assert.throws(function() {
|
||||
JSON.parse(body.toString('utf8'))
|
||||
})
|
||||
require('zlib').gunzip(body, function(err, buf) {
|
||||
assert(!err)
|
||||
assert.equal(err, null)
|
||||
body = JSON.parse(buf)
|
||||
assert.equal(body.name, 'testexp_gzip')
|
||||
assert.equal(Object.keys(body.versions).length, 9)
|
||||
|
|
|
@ -5,8 +5,6 @@ module.exports = function() {
|
|||
var express = process.express
|
||||
|
||||
describe('Incomplete', function() {
|
||||
var on_tarball
|
||||
|
||||
before(function() {
|
||||
express.get('/testexp-incomplete', function(_, res) {
|
||||
res.send({
|
||||
|
@ -49,12 +47,14 @@ module.exports = function() {
|
|||
})
|
||||
|
||||
server.request({uri:'/testexp-incomplete/-/'+type+'.tar.gz'}, function(err, res, body) {
|
||||
assert.equal(err, null)
|
||||
if (type !== 'chunked') assert.equal(res.headers['content-length'], 1e6)
|
||||
assert(body.match(/test test test/))
|
||||
})
|
||||
|
||||
function cb() {
|
||||
server.request({uri:'/testexp-incomplete/-/'+type+'.tar.gz'}, function(err, res, body) {
|
||||
assert.equal(err, null)
|
||||
assert.equal(body.error, 'internal server error')
|
||||
_cb()
|
||||
})
|
||||
|
|
|
@ -4,11 +4,6 @@ require('./lib/startup')
|
|||
var assert = require('assert')
|
||||
var async = require('async')
|
||||
var exec = require('child_process').exec
|
||||
var crypto = require('crypto')
|
||||
|
||||
function readfile(x) {
|
||||
return require('fs').readFileSync(__dirname + '/' + x)
|
||||
}
|
||||
|
||||
describe('Func', function() {
|
||||
var server = process.server
|
||||
|
@ -30,7 +25,8 @@ describe('Func', function() {
|
|||
server.debug(function(res, body) {
|
||||
server.pid = body.pid
|
||||
exec('lsof -p ' + Number(server.pid), function(err, result) {
|
||||
server.fdlist = result
|
||||
assert.equal(err, null)
|
||||
server.fdlist = result.replace(/ +/g, ' ')
|
||||
cb()
|
||||
})
|
||||
})
|
||||
|
@ -67,12 +63,15 @@ describe('Func', function() {
|
|||
after(function(cb) {
|
||||
async.map([server, server2], function(server, cb) {
|
||||
exec('lsof -p ' + Number(server.pid), function(err, result) {
|
||||
assert.equal(server.fdlist, result.split('\n').filter(function(q) {
|
||||
assert.equal(err, null)
|
||||
result = result.split('\n').filter(function(q) {
|
||||
if (q.match(/TCP .*->.* \(ESTABLISHED\)/)) return false
|
||||
if (q.match(/\/libcrypt-[^\/]+\.so/)) return false
|
||||
if (q.match(/\/node_modules\/crypt3\/build\/Release/)) return false
|
||||
return true
|
||||
}).join('\n'))
|
||||
}).join('\n').replace(/ +/g, ' ')
|
||||
|
||||
assert.equal(server.fdlist, result)
|
||||
cb()
|
||||
})
|
||||
}, cb)
|
||||
|
|
|
@ -5,7 +5,7 @@ module.exports = function(name, version) {
|
|||
"version": version || "0.0.0",
|
||||
"dist": {
|
||||
"shasum": "fake",
|
||||
"tarball": "http://localhost:55551/"+escape(name)+"/-/blahblah"
|
||||
"tarball": "http://localhost:55551/"+encodeURIComponent(name)+"/-/blahblah"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
var assert = require('assert')
|
||||
var fork = require('child_process').fork
|
||||
var express = require('express')
|
||||
var readfile = require('fs').readFileSync
|
||||
var rimraf = require('rimraf')
|
||||
var Server = require('./server')
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ module.exports = function() {
|
|||
method: 'PUT',
|
||||
json: JSON.parse(readfile('fixtures/newnpmreg.json')),
|
||||
}, function(err, res, body) {
|
||||
assert.equal(err, null)
|
||||
assert.equal(res.statusCode, 201)
|
||||
cb()
|
||||
})
|
||||
|
@ -72,6 +73,7 @@ module.exports = function() {
|
|||
|
||||
it('server1 - readme', function(cb) {
|
||||
server.request({uri:'/-/readme/testpkg-newnpmreg'}, function(err, res, body) {
|
||||
assert.equal(err, null)
|
||||
assert.equal(res.statusCode, 200)
|
||||
assert.equal(body, '<p>blah blah blah</p>\n')
|
||||
cb()
|
||||
|
@ -80,6 +82,7 @@ module.exports = function() {
|
|||
|
||||
it('server2 - readme', function(cb) {
|
||||
server2.request({uri:'/-/readme/testpkg-newnpmreg'}, function(err, res, body) {
|
||||
assert.equal(err, null)
|
||||
assert.equal(res.statusCode, 200)
|
||||
assert.equal(body, '<p>blah blah blah</p>\n')
|
||||
cb()
|
||||
|
@ -114,6 +117,7 @@ module.exports = function() {
|
|||
|
||||
it('server1 - search', function(cb) {
|
||||
server.request({uri:'/-/all'}, function(err, res, body) {
|
||||
assert.equal(err, null)
|
||||
assert.equal(res.statusCode, 200)
|
||||
check(body)
|
||||
cb()
|
||||
|
@ -122,6 +126,7 @@ module.exports = function() {
|
|||
|
||||
it('server2 - search', function(cb) {
|
||||
server2.request({uri:'/-/all'}, function(err, res, body) {
|
||||
assert.equal(err, null)
|
||||
assert.equal(res.statusCode, 200)
|
||||
check(body)
|
||||
cb()
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
require('./lib/startup')
|
||||
|
||||
var assert = require('assert')
|
||||
var async = require('async')
|
||||
var crypto = require('crypto')
|
||||
|
||||
function readfile(x) {
|
||||
|
|
|
@ -1,12 +1,9 @@
|
|||
var assert = require('assert')
|
||||
var async = require('async')
|
||||
var readfile = require('fs').readFileSync
|
||||
var ex = module.exports
|
||||
var _oksum = 0
|
||||
|
||||
module.exports = function() {
|
||||
var server = process.server
|
||||
var server2 = process.server2
|
||||
|
||||
describe('race', function() {
|
||||
before(function(cb) {
|
||||
|
@ -33,11 +30,13 @@ module.exports = function() {
|
|||
|
||||
async.parallel(fns, function(err, res) {
|
||||
var okcount = 0
|
||||
, failcount = 0
|
||||
var failcount = 0
|
||||
|
||||
assert.equal(err, null)
|
||||
|
||||
res.forEach(function(arr) {
|
||||
var resp = arr[0]
|
||||
, body = arr[1]
|
||||
var body = arr[1]
|
||||
|
||||
if (resp.statusCode === 201 && ~body.ok.indexOf('published')) okcount++
|
||||
if (resp.statusCode === 409 && ~body.error.indexOf('already present')) failcount++
|
||||
|
@ -65,11 +64,12 @@ module.exports = function() {
|
|||
|
||||
async.parallel(fns, function(err, res) {
|
||||
var okcount = 0
|
||||
, failcount = 0
|
||||
var failcount = 0
|
||||
|
||||
assert.equal(err, null)
|
||||
res.forEach(function(arr) {
|
||||
var resp = arr[0]
|
||||
, body = arr[1]
|
||||
var body = arr[1]
|
||||
if (resp.statusCode === 201 && ~body.ok.indexOf('published')) okcount++
|
||||
if (resp.statusCode === 409 && ~body.error.indexOf('already present')) failcount++
|
||||
if (resp.statusCode === 503 && ~body.error.indexOf('unavailable')) failcount++
|
||||
|
|
|
@ -41,12 +41,14 @@ module.exports = function() {
|
|||
}
|
||||
|
||||
server.request({uri:'/testexp-racycrash/-/test.tar.gz'}, function(err, res, body) {
|
||||
assert.equal(err, null)
|
||||
assert.equal(body, 'test test test\n')
|
||||
})
|
||||
|
||||
function cb() {
|
||||
// test for NOT crashing
|
||||
server.request({uri:'/testexp-racycrash'}, function(err, res, body) {
|
||||
assert.equal(err, null)
|
||||
assert.equal(res.statusCode, 200)
|
||||
_cb()
|
||||
})
|
||||
|
@ -59,6 +61,7 @@ module.exports = function() {
|
|||
}
|
||||
|
||||
server.request({uri:'/testexp-racycrash/-/test.tar.gz'}, function(err, res, body) {
|
||||
assert.equal(err, null)
|
||||
assert.equal(body.error, 'internal server error')
|
||||
cb()
|
||||
})
|
||||
|
|
|
@ -11,7 +11,6 @@ function sha(x) {
|
|||
module.exports = function() {
|
||||
var server = process.server
|
||||
var server2 = process.server2
|
||||
var express = process.express
|
||||
|
||||
describe('test-scoped', function() {
|
||||
before(function(cb) {
|
||||
|
@ -23,6 +22,7 @@ module.exports = function() {
|
|||
method: 'PUT',
|
||||
json: JSON.parse(readfile('fixtures/scoped.json')),
|
||||
}, function(err, res, body) {
|
||||
assert.equal(err, null)
|
||||
assert.equal(res.statusCode, 201)
|
||||
cb()
|
||||
})
|
||||
|
|
|
@ -2,7 +2,6 @@ var assert = require('assert')
|
|||
|
||||
module.exports = function() {
|
||||
var server = process.server
|
||||
var server2 = process.server2
|
||||
|
||||
describe('Security', function() {
|
||||
before(server.add_package.bind(server, 'testpkg-sec'))
|
||||
|
@ -25,11 +24,14 @@ module.exports = function() {
|
|||
|
||||
it('__proto__, connect stuff', function(cb) {
|
||||
server.request({uri:'/testpkg-sec?__proto__=1'}, function(err, res, body) {
|
||||
assert.equal(err, null)
|
||||
|
||||
// test for NOT outputting stack trace
|
||||
assert(!body || typeof(body) === 'object' || body.indexOf('node_modules') === -1)
|
||||
|
||||
// test for NOT crashing
|
||||
server.request({uri:'/testpkg-sec'}, function(err, res, body) {
|
||||
assert.equal(err, null)
|
||||
assert.equal(res.statusCode, 200)
|
||||
cb()
|
||||
})
|
||||
|
@ -38,6 +40,7 @@ module.exports = function() {
|
|||
|
||||
it('do not return package.json as an attachment', function(cb) {
|
||||
server.request({uri:'/testpkg-sec/-/package.json'}, function(err, res, body) {
|
||||
assert.equal(err, null)
|
||||
assert.equal(res.statusCode, 403)
|
||||
assert(body.error.match(/invalid filename/))
|
||||
cb()
|
||||
|
@ -46,6 +49,7 @@ module.exports = function() {
|
|||
|
||||
it('silly things - reading #1', function(cb) {
|
||||
server.request({uri:'/testpkg-sec/-/../../../../../../../../etc/passwd'}, function(err, res, body) {
|
||||
assert.equal(err, null)
|
||||
assert.equal(res.statusCode, 404)
|
||||
cb()
|
||||
})
|
||||
|
@ -53,6 +57,7 @@ module.exports = function() {
|
|||
|
||||
it('silly things - reading #2', function(cb) {
|
||||
server.request({uri:'/testpkg-sec/-/%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2fetc%2fpasswd'}, function(err, res, body) {
|
||||
assert.equal(err, null)
|
||||
assert.equal(res.statusCode, 403)
|
||||
assert(body.error.match(/invalid filename/))
|
||||
cb()
|
||||
|
|
|
@ -40,6 +40,7 @@ module.exports = function() {
|
|||
;['0.1.1alpha', '0.1.1-alpha', '0000.00001.001-alpha'].forEach(function(ver) {
|
||||
it('fetching '+ver, function(cb) {
|
||||
server.request({uri:'/testexp_tags/'+ver}, function(err, res, body) {
|
||||
assert.equal(err, null)
|
||||
assert.equal(res.statusCode, 200)
|
||||
assert.equal(body.version, '0.1.1alpha')
|
||||
cb()
|
||||
|
|
32
test/unit/listen_addr.js
Normal file
32
test/unit/listen_addr.js
Normal file
|
@ -0,0 +1,32 @@
|
|||
var assert = require('assert')
|
||||
var parse = require('../../lib/utils').parse_address
|
||||
|
||||
describe('Parse address', function() {
|
||||
function addTest(what, proto, host, port) {
|
||||
it(what, function() {
|
||||
if (proto === null) {
|
||||
assert.strictEqual(parse(what), null)
|
||||
} else {
|
||||
assert.deepEqual(parse(what), {
|
||||
proto: proto,
|
||||
host: host,
|
||||
port: port,
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
addTest('4873', 'http', 'localhost', '4873')
|
||||
addTest(':4873', 'http', 'localhost', '4873')
|
||||
addTest('blah:4873', 'http', 'blah', '4873')
|
||||
addTest('http://:4873', 'http', 'localhost', '4873')
|
||||
addTest('https::4873', 'https', 'localhost', '4873')
|
||||
addTest('https:blah:4873', 'https', 'blah', '4873')
|
||||
addTest('https://blah:4873/', 'https', 'blah', '4873')
|
||||
addTest('[::1]:4873', 'http', '::1', '4873')
|
||||
addTest('https:[::1]:4873', 'https', '::1', '4873')
|
||||
|
||||
addTest('blah', null)
|
||||
addTest('blah://4873', null)
|
||||
addTest('https://blah:4873///', null)
|
||||
})
|
|
@ -38,6 +38,7 @@ describe('toplevel', function() {
|
|||
request({
|
||||
url: 'http://localhost:' + port + '/',
|
||||
}, function(err, res, body) {
|
||||
assert.equal(err, null)
|
||||
assert(body.match(/<title>Sinopia<\/title>/))
|
||||
done()
|
||||
})
|
||||
|
@ -47,6 +48,7 @@ describe('toplevel', function() {
|
|||
request({
|
||||
url: 'http://localhost:' + port + '/whatever',
|
||||
}, function(err, res, body) {
|
||||
assert.equal(err, null)
|
||||
assert(body.match(/no such package available/))
|
||||
done()
|
||||
})
|
||||
|
|
|
@ -21,11 +21,11 @@ describe('Validate', function() {
|
|||
assert( !validate('some/thing') )
|
||||
assert( !validate('some\\thing') )
|
||||
})
|
||||
|
||||
|
||||
it('no hidden', function() {
|
||||
assert( !validate('.bin') )
|
||||
})
|
||||
|
||||
|
||||
it('no reserved', function() {
|
||||
assert( !validate('favicon.ico') )
|
||||
assert( !validate('node_modules') )
|
||||
|
|
Loading…
Add table
Reference in a new issue