qwgit / lib / namespaces.js
http{/,s} git server
git clone http://git.nthia.dev/qwgit

const EventEmitter = require('events')
const actions = ['create','remove']
module.exports = Namespaces

function Namespaces(opts) {
  if (!(this instanceof Namespaces)) return new Namespaces(opts)
  EventEmitter.call(this)
  this._ns = new Map
  for (let i = 0; i < opts.data.length; i++) {
    let d = opts.data[i]
    this._ns.set(d.id, d)
  }
  this._idns = new Map
  for (let i = 0; i < actions.length; i++) {
    let ns = new Map
    let action = actions[i]
    this._idns.set(action, ns)
    for (let j = 0; j < opts.data.length; j++) {
      let d = opts.data[j]
      if (!Array.isArray(d[action])) continue
      for (let k = 0; k < d[action].length; k++) {
        let id = d[action][k]
        let rids = ns.get(id) ?? new Set
        rids.add(d.id)
        ns.set(id, rids)
      }
    }
  }
}
Namespaces.prototype = Object.create(EventEmitter.prototype)

Namespaces.prototype.isAuthorized = function (action, rpath, ids) {
  if (action === 'rename') {
    return this.isAuthorized('create', rpath, ids) && this.isAuthorized('remove', rpath, ids)
  }
  if (!/^\//.test(rpath)) rpath = '/' + rpath
  let ns = this._idns.get(action)
  for (let i = 0; i < ids.length; i++) {
    let id = ids[i]
    let rids = ns.get(id)
    if (!rids) continue
    for (let rid of rids.values()) {
      let d = this._ns.get(rid)
      for (let j = 0; j < d.paths.length; j++) {
        let dp = d.paths[j].replace(/[\/]*$/,'/')
        if (d.paths[j] === rpath || rpath.startsWith(dp)) {
          return true
        }
      }
    }
  }
  return false
}