http{/,s} git server
git clone http://git.nthia.dev/qwgit
let { nextTick } = process
module.exports = Auth
function Auth(data) {
if (!(this instanceof Auth)) return new Auth(data)
this.data = []
this._groups = new Map
if (Array.isArray(data)) this.load(data)
}
Auth.prototype.clear = function () {
this.data = []
}
Auth.prototype.load = function (data) {
data.forEach(creds => this.add(creds))
}
Auth.prototype.add = function (d) {
d = Object.assign({}, d)
if (!Array.isArray(d.logins)) d.logins = []
if (!Array.isArray(d.ids)) d.ids = []
if (!Array.isArray(d.groups)) d.groups = []
d.ids = d.ids.map(id => id === '/' ? '/' : id.replace(/^\//, ''))
d.logins = d.logins.map(l => {
l = Object.assign({}, l)
if (l.fingerprint512 !== undefined) l.fingerprint512 = normfp(l.fingerprint512)
return l
})
d.groups.forEach(g => {
let groups = this._groups.get(g) ?? new Set
d.ids.forEach(id => groups.add(id))
this._groups.set(g, groups)
})
this.data.push(d)
}
Auth.prototype.challenge = function (id, creds, cb) {
if (creds.fingerprint512 !== undefined) {
creds = Object.assign({}, creds, { fingerprint512: normfp(creds.fingerprint512) })
}
if (typeof id === 'number') id = String(id)
for (let i = 0; i < this.data.length; i++) {
let d = this.data[i]
if (!checkId(id, d.ids)) continue
for (let j = 0; j < d.logins.length; j++) {
let l = d.logins[j]
if (l.type === 'fingerprint') {
if (l.fingerprint512 === undefined) continue
if (l.fingerprint512 === creds.fingerprint512) {
return nextTick(cb, null, d)
}
}
}
}
nextTick(cb, null, null)
}
Auth.prototype.find = function (creds, cb) {
if (creds.fingerprint512 !== undefined) {
creds = Object.assign({}, creds, { fingerprint512: normfp(creds.fingerprint512) })
}
let ids = []
for (let i = 0; i < this.data.length; i++) {
let d = this.data[i]
for (let j = 0; j < d.logins.length; j++) {
let l = d.logins[j]
if (l.type === 'fingerprint') {
if (l.fingerprint512 === undefined) continue
if (l.fingerprint512 === creds.fingerprint512) {
ids = ids.concat(d.ids)
}
}
}
}
nextTick(cb, null, ids)
}
function normfp(x) { return String(x).toLowerCase().replace(/:/g,'') }
function checkId(id, ids) {
if (ids.includes(id)) return true
for (let i of ids) {
if (i === '/') return true
if (i.endsWith('/') && id.startsWith(i)) return true
}
return false
}