mirror of
https://github.com/aljazceru/gitpear.git
synced 2025-12-17 14:14:22 +01:00
20
src/acl.js
Normal file
20
src/acl.js
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
const home = require('./home')
|
||||||
|
|
||||||
|
const roles = {
|
||||||
|
admin: {
|
||||||
|
description: 'Read and write to all branches',
|
||||||
|
},
|
||||||
|
contributor: {
|
||||||
|
description: 'Read and write to all branches except protected ones',
|
||||||
|
},
|
||||||
|
viewer: {
|
||||||
|
description: 'Read all branches',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
const DEFAULT_ACL = {
|
||||||
|
visibibility: 'public', // public|private
|
||||||
|
protectedBranches: ['master'],
|
||||||
|
ACL: {}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -11,7 +11,7 @@ const crypto = require('hypercore-crypto')
|
|||||||
|
|
||||||
const git = require('./git.js')
|
const git = require('./git.js')
|
||||||
const home = require('./home')
|
const home = require('./home')
|
||||||
const acl = require('./acl')
|
const auth = require('./auth')
|
||||||
|
|
||||||
const fs = require('fs')
|
const fs = require('fs')
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ swarm.on('connection', async (socket) => {
|
|||||||
|
|
||||||
let payload = { body: { url, method: 'get-repos' } }
|
let payload = { body: { url, method: 'get-repos' } }
|
||||||
if (process.env.GIT_PEAR_AUTH) {
|
if (process.env.GIT_PEAR_AUTH) {
|
||||||
payload.header = await acl.getToken(payload.body)
|
payload.header = await auth.getToken(payload.body)
|
||||||
}
|
}
|
||||||
|
|
||||||
const reposRes = await rpc.request('get-repos', Buffer.from(JSON.stringify(payload)))
|
const reposRes = await rpc.request('get-repos', Buffer.from(JSON.stringify(payload)))
|
||||||
@@ -71,10 +71,9 @@ swarm.on('connection', async (socket) => {
|
|||||||
|
|
||||||
await drive.core.update({ wait: true })
|
await drive.core.update({ wait: true })
|
||||||
|
|
||||||
// TODO: ACL
|
|
||||||
payload = { body: { url, method: 'get-refs', data: repoName }}
|
payload = { body: { url, method: 'get-refs', data: repoName }}
|
||||||
if (process.env.GIT_PEAR_AUTH) {
|
if (process.env.GIT_PEAR_AUTH) {
|
||||||
payload.header = await acl.getToken(payload.body)
|
payload.header = await auth.getToken(payload.body)
|
||||||
}
|
}
|
||||||
const refsRes = await rpc.request('get-refs', Buffer.from(JSON.stringify(payload)))
|
const refsRes = await rpc.request('get-refs', Buffer.from(JSON.stringify(payload)))
|
||||||
|
|
||||||
@@ -128,7 +127,7 @@ async function talkToGit (refs, drive, repoName, rpc, commit) {
|
|||||||
method
|
method
|
||||||
} }
|
} }
|
||||||
if (process.env.GIT_PEAR_AUTH) {
|
if (process.env.GIT_PEAR_AUTH) {
|
||||||
payload.header = await acl.getToken(payload.body)
|
payload.header = await auth.getToken(payload.body)
|
||||||
}
|
}
|
||||||
const res = await rpc.request(method, Buffer.from(JSON.stringify(payload)))
|
const res = await rpc.request(method, Buffer.from(JSON.stringify(payload)))
|
||||||
|
|
||||||
|
|||||||
36
src/home.js
36
src/home.js
@@ -10,38 +10,10 @@ function createAppFolder (name) {
|
|||||||
fs.mkdirSync(`${APP_HOME}/${name}/code`, { recursive: true })
|
fs.mkdirSync(`${APP_HOME}/${name}/code`, { recursive: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
function shareAppFolder (name, entry) {
|
function shareAppFolder (name) {
|
||||||
const p = `${APP_HOME}/${name}/.git-daemon-export-ok`
|
fs.openSync(`${APP_HOME}/${name}/.git-daemon-export-ok`, 'w')
|
||||||
fs.openSync(p, 'a')
|
|
||||||
const aclFile = fs.readFileSync(p, 'utf8')
|
|
||||||
const aclJson = JSON.parse(aclFile || '{ "protectedBranches": ["master"], "ACL": {}}')
|
|
||||||
|
|
||||||
let [userId = '*', permissions = 'r', branch = '*'] = entry?.split(':') || []
|
|
||||||
|
|
||||||
if (!aclJson.ACL[userId]) aclJson.ACL[userId] = { [branch]: permissions }
|
|
||||||
fs.writeFileSync(p, JSON.stringify(aclJson))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function addProtectedBranch (name, branch) {
|
|
||||||
const aclFile = fs.readFileSync(`${APP_HOME}/${name}/.git-daemon-export-ok`, 'utf8')
|
|
||||||
const aclJson = JSON.parse(aclFile || '{ "protectedBranches": [], "ACL": {}}')
|
|
||||||
if (!aclJson.protectedBranches.includes(branch)) aclJson.protectedBranches.push(branch)
|
|
||||||
fs.writeFileSync(aclFile, JSON.stringify(aclJson))
|
|
||||||
}
|
|
||||||
|
|
||||||
function removeProtectedBranch (name, branch) {
|
|
||||||
const aclFile = fs.readFileSync(`${APP_HOME}/${name}/.git-daemon-export-ok`, 'a')
|
|
||||||
const aclJson = JSON.parse(aclFile || '{ "protectedBranches": [], "ACL": {}}')
|
|
||||||
aclJson.protectedBranches = aclJson.protectedBranches.filter(b => b !== branch)
|
|
||||||
fs.writeFileSync(aclFile, JSON.stringify(aclJson))
|
|
||||||
}
|
|
||||||
|
|
||||||
function removeUserFromACL (name, userId) {
|
|
||||||
const aclFile = fs.readFileSync(`${APP_HOME}/${name}/.git-daemon-export-ok`, 'a')
|
|
||||||
const aclJson = JSON.parse(aclFile || '{ "protectedBranches": [], "ACL": {}}')
|
|
||||||
delete aclJson.ACL[userId]
|
|
||||||
fs.writeFileSync(aclFile, JSON.stringify(aclJson))
|
|
||||||
}
|
|
||||||
|
|
||||||
function unshareAppFolder (name) {
|
function unshareAppFolder (name) {
|
||||||
fs.unlinkSync(`${APP_HOME}/${name}/.git-daemon-export-ok`)
|
fs.unlinkSync(`${APP_HOME}/${name}/.git-daemon-export-ok`)
|
||||||
@@ -57,10 +29,6 @@ function isShared (name) {
|
|||||||
|
|
||||||
function getACL (name) {
|
function getACL (name) {
|
||||||
if (!fs.existsSync(`${APP_HOME}/${name}/.git-daemon-export-ok`)) throw new Error('Repo is not shared')
|
if (!fs.existsSync(`${APP_HOME}/${name}/.git-daemon-export-ok`)) throw new Error('Repo is not shared')
|
||||||
|
|
||||||
const aclFile = fs.readFileSync(`${APP_HOME}/${name}/.git-daemon-export-ok`, 'utf8')
|
|
||||||
aclJson = JSON.parse(aclFile || '{ "protectedBranches": [], "ACL": {}}')
|
|
||||||
return aclJson
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function list (sharedOnly) {
|
function list (sharedOnly) {
|
||||||
|
|||||||
16
src/rpc.js
16
src/rpc.js
@@ -1,7 +1,7 @@
|
|||||||
const ProtomuxRPC = require('protomux-rpc')
|
const ProtomuxRPC = require('protomux-rpc')
|
||||||
const { spawn } = require('child_process')
|
const { spawn } = require('child_process')
|
||||||
const home = require('./home')
|
const home = require('./home')
|
||||||
const acl = require('./acl')
|
const auth = require('./auth')
|
||||||
|
|
||||||
module.exports = class RPC {
|
module.exports = class RPC {
|
||||||
constructor (announcedRefs, repositories, drives) {
|
constructor (announcedRefs, repositories, drives) {
|
||||||
@@ -98,7 +98,7 @@ module.exports = class RPC {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async parseReq(publicKey, req, access, branch = '*') {
|
async parseReq(publicKey, req) {
|
||||||
if (!req) throw new Error('Request is empty')
|
if (!req) throw new Error('Request is empty')
|
||||||
let request = JSON.parse(req.toString())
|
let request = JSON.parse(req.toString())
|
||||||
const parsed = {
|
const parsed = {
|
||||||
@@ -116,22 +116,12 @@ module.exports = class RPC {
|
|||||||
if (process.env.GIT_PEAR_AUTH === 'naitive') {
|
if (process.env.GIT_PEAR_AUTH === 'naitive') {
|
||||||
userId = publicKey
|
userId = publicKey
|
||||||
} else {
|
} else {
|
||||||
userId = (await acl.getId({ ...request.body, payload: request.header })).userId
|
userId = (await auth.getId({ ...request.body, payload: request.header })).userId
|
||||||
}
|
}
|
||||||
const aclObj = home.getACL(parsed.repoName)
|
const aclObj = home.getACL(parsed.repoName)
|
||||||
const userACL = aclObj[userId] || aclObj['*']
|
const userACL = aclObj[userId] || aclObj['*']
|
||||||
if (!userACL) throw new Error('You are not allowed to access this repo')
|
if (!userACL) throw new Error('You are not allowed to access this repo')
|
||||||
|
|
||||||
if (aclObj.protectecBranches.includes(branch)) {
|
|
||||||
// protected branch must have exaplicit access grant
|
|
||||||
if (access === 'w') {
|
|
||||||
|
|
||||||
} else {
|
|
||||||
//
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return parsed
|
return parsed
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user