diff --git a/Readme.md b/Readme.md index 03e8c68..9efbebb 100644 --- a/Readme.md +++ b/Readme.md @@ -45,12 +45,21 @@ All data will be persisted in application directory (default `~/.gitpear`). To c ### ACL (for authenticated access to enable support of PUSH) -Support of `push` capabilities only enabled for authenticated users. Currently supported authentication is based on [NIP98](https://github.com/nostr-protocol/nips/blob/master/98.md). -To start daemon with authenticated support provide environment varibales `GIT_PEAR_AUTH` with value `nip98` and `GIT_PEAR_AUTH_NSEC` with value of your [NIP19 nsec](https://github.com/nostr-protocol/nips/blob/master/19.md). +Support of `push` capabilities only enabled for authenticated users. Currently supported authentications are based on: +* [noise](https://github.com/libp2p/specs/blob/master/noise/README.md); +* [NIP98](https://github.com/nostr-protocol/nips/blob/master/98.md). + +To start daemon with authenticated support provide environment varibales `GIT_PEAR_AUTH` with values `nip98` or `native`. +The `nip98` also requires `GIT_PEAR_AUTH_NSEC` with value of your [NIP19 nsec](https://github.com/nostr-protocol/nips/blob/master/19.md). + For example: ``` GIT_PEAR_AUTH=nip98 GIT_PEAR_AUTH_NSEC=nsec.... git pear daemon -s ``` +or +``` +GIT_PEAR_AUTH=native git pear daemon -s +``` To manage access to repository use one or combination of the following commands, if `path` is not provide the command will be executed in the current directory. For `userId` use [NIP19 npub](https://github.com/nostr-protocol/nips/blob/master/19.md). @@ -120,18 +129,20 @@ git pull Collaboration is possible with the following flow between Carol and David in a peer-to-peer manner. +Supported authentication methods are `native` and `nip98`. The `nip98` authentication, requires environment variable `GIT_PEAR_AUTH_NSEC` with nsec + ### Carol steps (as a server of code) 1. Start daemon -* `GIT_PEAR_AUTH_NSEC= GIT_PEAR_AUTH='nip98' git pear daemon -s` +* `GIT_PEAR_AUTH='native' git pear daemon -s` 2. Go to repository * `cd repo` 3. Initialize git pear repository * `git pear init .` 4. Share repository wit hviben visibility () - (default is `public`) -* `git pear share . ` +* `git pear share . public` 5. Add Daviv as a `contirbutor`. 6. List David's npub as a contributor -* `git pear acl add :contributor` +* `git pear acl add :contributor` 7. Retreive repo url and share it with Dave * `git pear list -s` @@ -139,14 +150,14 @@ Collaboration is possible with the following flow between Carol and David in a p 1. Start daemon. This will be needed later for push. Not that no auth or sec are provided which means that push to this place will not be supportedd. * `git pear daemon -s` 2. Clone repository. Authorization data and type are necesary for server (Carol) to grant corresponding access persmissions -* `GIT_PEAR_AUTH_NSEC= GIT_PEAR_AUTH='nip98' git clone pear:///` +* `GIT_PEAR_AUTH='native' git clone pear:///` 3. Do the necessary change in separate branch * `git checkout -b feat/david` * do change * `git add .` * `git commit -s -m 'made by David'` 4. Push branch to origin -* `GIT_PEAR_AUTH_NSEC= GIT_PEAR_AUTH='nip98' git push origin feat/david` +* `GIT_PEAR_AUTH='native' git push origin feat/david` ### Carol steps 1. For Carol the changes will arrive as branch `feat/david` into her `pear` diff --git a/src/git-remote-pear.js b/src/git-remote-pear.js index 088b9e2..31ac3a7 100755 --- a/src/git-remote-pear.js +++ b/src/git-remote-pear.js @@ -28,7 +28,7 @@ const targetKey = matches[1] const repoName = matches[2] const store = new Corestore(RAM) -const swarm = new Hyperswarm({ keypair: home.getKeyPair() }) +const swarm = new Hyperswarm({ keyPair: home.getKeyPair() }) if (!home.isDaemonRunning()) { console.error('Please start git pear daemon') @@ -42,7 +42,7 @@ swarm.on('connection', async (socket) => { const rpc = new ProtomuxRPC(socket) let payload = { body: { url, method: 'get-repos' } } - if (process.env.GIT_PEAR_AUTH) { + if (process.env.GIT_PEAR_AUTH && process.env.GIT_PEAR_AUTH !== 'native') { payload.header = await auth.getToken(payload.body) } @@ -73,7 +73,7 @@ swarm.on('connection', async (socket) => { await drive.core.update({ wait: true }) payload = { body: { url, method: 'get-refs', data: repoName }} - if (process.env.GIT_PEAR_AUTH) { + if (process.env.GIT_PEAR_AUTH && process.env.GIT_PEAR_AUTH !== 'native') { payload.header = await auth.getToken(payload.body) } const refsRes = await rpc.request('get-refs', Buffer.from(JSON.stringify(payload))) @@ -101,10 +101,6 @@ async function talkToGit (refs, drive, repoName, rpc, commit) { const isDelete = !src const isForce = src.startsWith('+') - if (!home.isShared(repoName)) { - home.shareAppFolder(name) - } - dst = dst.replace('refs/heads/', '').replace('\n\n', '') try { home.createAppFolder(repoName) } catch (e) { } @@ -134,7 +130,7 @@ async function talkToGit (refs, drive, repoName, rpc, commit) { data: `${dst}#${commit}`, method } } - if (process.env.GIT_PEAR_AUTH) { + if (process.env.GIT_PEAR_AUTH && process.env.GIT_PEAR_AUTH !== 'native') { payload.header = await auth.getToken(payload.body) } const res = await rpc.request(method, Buffer.from(JSON.stringify(payload))) diff --git a/src/rpc.js b/src/rpc.js index e3338cc..90087c3 100755 --- a/src/rpc.js +++ b/src/rpc.js @@ -1,4 +1,5 @@ const ProtomuxRPC = require('protomux-rpc') +const SecretStream = require('@hyperswarm/secret-stream') const { spawn } = require('child_process') const home = require('./home') const auth = require('./auth') @@ -16,19 +17,21 @@ module.exports = class RPC { if (this.connections[peerInfo.publicKey]) return this.connections[peerInfo.publicKey] const rpc = new ProtomuxRPC(socket) + rpc.on('error', err => console.error('rpc error', err)) + rpc.on('close', () => delete this.connections[peerInfo.publicKey]) // XXX: handshaking can be used for access and permission management // for example check of peerInfo.publicKey is in a list of allowed keys // which can in turn be stored in a .git-daemon-export-ok file /* -- PULL HANDLERS -- */ - rpc.respond('get-repos', async req => await this.getReposHandler(peerInfo.publicKey, req)) - rpc.respond('get-refs', async req => await this.getRefsHandler(peerInfo.publicKey, req)) + rpc.respond('get-repos', async req => await this.getReposHandler(socket.remotePublicKey, req)) + rpc.respond('get-refs', async req => await this.getRefsHandler(socket.remotePublicKey, req)) if (process.env.GIT_PEAR_AUTH) { /* -- PUSH HANDLERS -- */ - rpc.respond('push', async req => await this.pushHandler(peerInfo.publicKey, req)) - rpc.respond('f-push', async req => await this.forcePushHandler(peerInfo.publicKey, req)) - rpc.respond('d-branch', async req => await this.deleteBranchHandler(peerInfo.publicKey, req)) + rpc.respond('push', async req => await this.pushHandler(socket.remotePublicKey, req)) + rpc.respond('f-push', async req => await this.forcePushHandler(socket.remotePublicKey, req)) + rpc.respond('d-branch', async req => await this.deleteBranchHandler(socket.remotePublicKey, req)) } this.connections[peerInfo.publicKey] = rpc @@ -150,6 +153,7 @@ module.exports = class RPC { async authenticate (publicKey, request) { if (!process.env.GIT_PEAR_AUTH) return publicKey.toString('hex') + if (process.env.GIT_PEAR_AUTH === 'native') return publicKey.toString('hex') if (!request.header) throw new Error('You are not allowed to access this repo') return (await auth.getId({ ...request.body, payload: request.header })).userId