mirror of
https://github.com/aljazceru/gitpear.git
synced 2025-12-17 22:24:22 +01:00
@@ -48,7 +48,7 @@ All data will be persisted in application directory (default `~/.gitpear`). To c
|
|||||||
|
|
||||||
* `git pear list [-s, --shared]` - list all or (only shared) repositories
|
* `git pear list [-s, --shared]` - list all or (only shared) repositories
|
||||||
|
|
||||||
## Usage example
|
## Usage example (NO PUSH)
|
||||||
|
|
||||||
Please not this is only remote helper and its intention is only to enable direct `clone|fetch|pull` of repository hosted on private computer.
|
Please not this is only remote helper and its intention is only to enable direct `clone|fetch|pull` of repository hosted on private computer.
|
||||||
|
|
||||||
@@ -94,3 +94,5 @@ git checkout master
|
|||||||
git fetch origin
|
git fetch origin
|
||||||
git pull
|
git pull
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Usage example (PUSH)
|
||||||
|
|||||||
202
npm-shrinkwrap.json
generated
202
npm-shrinkwrap.json
generated
@@ -15,6 +15,7 @@
|
|||||||
"corestore": "^6.15.13",
|
"corestore": "^6.15.13",
|
||||||
"hyperdrive": "^11.6.3",
|
"hyperdrive": "^11.6.3",
|
||||||
"hyperswarm": "^4.7.13",
|
"hyperswarm": "^4.7.13",
|
||||||
|
"nostr-tools": "^2.1.5",
|
||||||
"protomux-rpc": "^1.5.1",
|
"protomux-rpc": "^1.5.1",
|
||||||
"random-access-memory": "^6.2.0"
|
"random-access-memory": "^6.2.0"
|
||||||
},
|
},
|
||||||
@@ -239,6 +240,47 @@
|
|||||||
"@jridgewell/sourcemap-codec": "^1.4.14"
|
"@jridgewell/sourcemap-codec": "^1.4.14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@noble/ciphers": {
|
||||||
|
"version": "0.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-0.2.0.tgz",
|
||||||
|
"integrity": "sha512-6YBxJDAapHSdd3bLDv6x2wRPwq4QFMUaB3HvljNBUTThDd12eSm7/3F+2lnfzx2jvM+S6Nsy0jEt9QbPqSwqRw==",
|
||||||
|
"funding": {
|
||||||
|
"url": "https://paulmillr.com/funding/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@noble/curves": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@noble/hashes": "1.3.2"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://paulmillr.com/funding/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@noble/curves/node_modules/@noble/hashes": {
|
||||||
|
"version": "1.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz",
|
||||||
|
"integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 16"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://paulmillr.com/funding/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@noble/hashes": {
|
||||||
|
"version": "1.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz",
|
||||||
|
"integrity": "sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 16"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://paulmillr.com/funding/"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@nodelib/fs.scandir": {
|
"node_modules/@nodelib/fs.scandir": {
|
||||||
"version": "2.1.5",
|
"version": "2.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
||||||
@@ -274,6 +316,53 @@
|
|||||||
"node": ">= 8"
|
"node": ">= 8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@scure/base": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "individual",
|
||||||
|
"url": "https://paulmillr.com/funding/"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/@scure/bip32": {
|
||||||
|
"version": "1.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.1.tgz",
|
||||||
|
"integrity": "sha512-osvveYtyzdEVbt3OfwwXFr4P2iVBL5u1Q3q4ONBfDY/UpOuXmOlbgwc1xECEboY8wIays8Yt6onaWMUdUbfl0A==",
|
||||||
|
"dependencies": {
|
||||||
|
"@noble/curves": "~1.1.0",
|
||||||
|
"@noble/hashes": "~1.3.1",
|
||||||
|
"@scure/base": "~1.1.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://paulmillr.com/funding/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@scure/bip32/node_modules/@noble/curves": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@noble/hashes": "1.3.1"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://paulmillr.com/funding/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@scure/bip39": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.1.tgz",
|
||||||
|
"integrity": "sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@noble/hashes": "~1.3.0",
|
||||||
|
"@scure/base": "~1.1.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://paulmillr.com/funding/"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/istanbul-lib-coverage": {
|
"node_modules/@types/istanbul-lib-coverage": {
|
||||||
"version": "2.0.6",
|
"version": "2.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz",
|
||||||
@@ -3008,6 +3097,36 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/nostr-tools": {
|
||||||
|
"version": "2.1.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/nostr-tools/-/nostr-tools-2.1.5.tgz",
|
||||||
|
"integrity": "sha512-Gug/j54YGQ0ewB09dZW3mS9qfXWFlcOQMlyb1MmqQsuNO/95mfNOQSBi+jZ61O++Y+jG99SzAUPFLopUsKf0MA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@noble/ciphers": "0.2.0",
|
||||||
|
"@noble/curves": "1.2.0",
|
||||||
|
"@noble/hashes": "1.3.1",
|
||||||
|
"@scure/base": "1.1.1",
|
||||||
|
"@scure/bip32": "1.3.1",
|
||||||
|
"@scure/bip39": "1.2.1"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"nostr-wasm": "v0.1.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"typescript": ">=5.0.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"typescript": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/nostr-wasm": {
|
||||||
|
"version": "0.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/nostr-wasm/-/nostr-wasm-0.1.0.tgz",
|
||||||
|
"integrity": "sha512-78BTryCLcLYv96ONU8Ws3Q1JzjlAt+43pWQhIl86xZmWeegYCNLPml7yQ+gG3vR6V5h4XGj+TxO+SS5dsThQIA==",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
"node_modules/object-assign": {
|
"node_modules/object-assign": {
|
||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||||
@@ -4390,7 +4509,7 @@
|
|||||||
"version": "5.3.3",
|
"version": "5.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz",
|
||||||
"integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==",
|
"integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==",
|
||||||
"dev": true,
|
"devOptional": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"tsc": "bin/tsc",
|
"tsc": "bin/tsc",
|
||||||
"tsserver": "bin/tsserver"
|
"tsserver": "bin/tsserver"
|
||||||
@@ -4838,6 +4957,31 @@
|
|||||||
"@jridgewell/sourcemap-codec": "^1.4.14"
|
"@jridgewell/sourcemap-codec": "^1.4.14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@noble/ciphers": {
|
||||||
|
"version": "0.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-0.2.0.tgz",
|
||||||
|
"integrity": "sha512-6YBxJDAapHSdd3bLDv6x2wRPwq4QFMUaB3HvljNBUTThDd12eSm7/3F+2lnfzx2jvM+S6Nsy0jEt9QbPqSwqRw=="
|
||||||
|
},
|
||||||
|
"@noble/curves": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==",
|
||||||
|
"requires": {
|
||||||
|
"@noble/hashes": "1.3.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@noble/hashes": {
|
||||||
|
"version": "1.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz",
|
||||||
|
"integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@noble/hashes": {
|
||||||
|
"version": "1.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz",
|
||||||
|
"integrity": "sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA=="
|
||||||
|
},
|
||||||
"@nodelib/fs.scandir": {
|
"@nodelib/fs.scandir": {
|
||||||
"version": "2.1.5",
|
"version": "2.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
||||||
@@ -4864,6 +5008,40 @@
|
|||||||
"fastq": "^1.6.0"
|
"fastq": "^1.6.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@scure/base": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA=="
|
||||||
|
},
|
||||||
|
"@scure/bip32": {
|
||||||
|
"version": "1.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.1.tgz",
|
||||||
|
"integrity": "sha512-osvveYtyzdEVbt3OfwwXFr4P2iVBL5u1Q3q4ONBfDY/UpOuXmOlbgwc1xECEboY8wIays8Yt6onaWMUdUbfl0A==",
|
||||||
|
"requires": {
|
||||||
|
"@noble/curves": "~1.1.0",
|
||||||
|
"@noble/hashes": "~1.3.1",
|
||||||
|
"@scure/base": "~1.1.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@noble/curves": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA==",
|
||||||
|
"requires": {
|
||||||
|
"@noble/hashes": "1.3.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@scure/bip39": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.1.tgz",
|
||||||
|
"integrity": "sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==",
|
||||||
|
"requires": {
|
||||||
|
"@noble/hashes": "~1.3.0",
|
||||||
|
"@scure/base": "~1.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/istanbul-lib-coverage": {
|
"@types/istanbul-lib-coverage": {
|
||||||
"version": "2.0.6",
|
"version": "2.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz",
|
||||||
@@ -6982,6 +7160,26 @@
|
|||||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||||
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="
|
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="
|
||||||
},
|
},
|
||||||
|
"nostr-tools": {
|
||||||
|
"version": "2.1.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/nostr-tools/-/nostr-tools-2.1.5.tgz",
|
||||||
|
"integrity": "sha512-Gug/j54YGQ0ewB09dZW3mS9qfXWFlcOQMlyb1MmqQsuNO/95mfNOQSBi+jZ61O++Y+jG99SzAUPFLopUsKf0MA==",
|
||||||
|
"requires": {
|
||||||
|
"@noble/ciphers": "0.2.0",
|
||||||
|
"@noble/curves": "1.2.0",
|
||||||
|
"@noble/hashes": "1.3.1",
|
||||||
|
"@scure/base": "1.1.1",
|
||||||
|
"@scure/bip32": "1.3.1",
|
||||||
|
"@scure/bip39": "1.2.1",
|
||||||
|
"nostr-wasm": "v0.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nostr-wasm": {
|
||||||
|
"version": "0.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/nostr-wasm/-/nostr-wasm-0.1.0.tgz",
|
||||||
|
"integrity": "sha512-78BTryCLcLYv96ONU8Ws3Q1JzjlAt+43pWQhIl86xZmWeegYCNLPml7yQ+gG3vR6V5h4XGj+TxO+SS5dsThQIA==",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
"object-assign": {
|
"object-assign": {
|
||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||||
@@ -8028,7 +8226,7 @@
|
|||||||
"version": "5.3.3",
|
"version": "5.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz",
|
||||||
"integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==",
|
"integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==",
|
||||||
"dev": true
|
"devOptional": true
|
||||||
},
|
},
|
||||||
"udx-native": {
|
"udx-native": {
|
||||||
"version": "1.7.12",
|
"version": "1.7.12",
|
||||||
|
|||||||
@@ -46,6 +46,7 @@
|
|||||||
"corestore": "^6.15.13",
|
"corestore": "^6.15.13",
|
||||||
"hyperdrive": "^11.6.3",
|
"hyperdrive": "^11.6.3",
|
||||||
"hyperswarm": "^4.7.13",
|
"hyperswarm": "^4.7.13",
|
||||||
|
"nostr-tools": "^2.1.5",
|
||||||
"protomux-rpc": "^1.5.1",
|
"protomux-rpc": "^1.5.1",
|
||||||
"random-access-memory": "^6.2.0"
|
"random-access-memory": "^6.2.0"
|
||||||
}
|
}
|
||||||
|
|||||||
20
src/acl/index.js
Normal file
20
src/acl/index.js
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
function getId(data) {
|
||||||
|
if (!process.env.GIT_PEAR_AUTH) return payload
|
||||||
|
if (process.env.GIT_PEAR_AUTH === 'nip98') {
|
||||||
|
const nip98 = require('./nip98')
|
||||||
|
return nip98.getId(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getToken(payload) {
|
||||||
|
if (!process.env.GIT_PEAR_AUTH) return userId
|
||||||
|
if (process.env.GIT_PEAR_AUTH === 'nip98') {
|
||||||
|
const nip98 = require('./nip98')
|
||||||
|
return nip98.getToken(payload)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
getId,
|
||||||
|
getToken
|
||||||
|
}
|
||||||
49
src/acl/nip98.js
Normal file
49
src/acl/nip98.js
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
const { nip98, nip19, finalizeEvent } = require('nostr-tools')
|
||||||
|
|
||||||
|
async function getToken({ url, method, data }) {
|
||||||
|
const { data: sK } = nip19.decode(process.env.GIT_PEAR_AUTH_NSEC)
|
||||||
|
return nip98.getToken(
|
||||||
|
url,
|
||||||
|
method,
|
||||||
|
(e) => finalizeEvent(e, sK),
|
||||||
|
false,
|
||||||
|
data
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME
|
||||||
|
async function getId({ payload, url, method, data }) {
|
||||||
|
const event = JSON.parse(Buffer.from(payload, 'base64').toString())
|
||||||
|
const isValid = await nip98.validateEvent(event, url, method, data)
|
||||||
|
if (!isValid) throw new Error('Invalid event')
|
||||||
|
return {
|
||||||
|
...event,
|
||||||
|
userId: nip19.npubEncode(event.pubkey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
getId,
|
||||||
|
getToken
|
||||||
|
}
|
||||||
|
|
||||||
|
// ;(async () => {
|
||||||
|
// const repo = 'gitpear'
|
||||||
|
// const url = `pear://d1672d338b8e24223cd0dc6c6b5e04ebabf091fc2b470204abdb98fa5fc59072/${repo}`
|
||||||
|
// const commit = '1837a4bae8497f71fb8f01305c3ace1e3dedcdba'
|
||||||
|
// const method = 'push'
|
||||||
|
// const branch = 'test'
|
||||||
|
// const data = `${branch}#${commit}`
|
||||||
|
//
|
||||||
|
// let payload
|
||||||
|
// let npub
|
||||||
|
//
|
||||||
|
// payload = await getToken({ url, method, data })
|
||||||
|
// npub = await getId({ payload, url, method, data })
|
||||||
|
//
|
||||||
|
// payload = await getToken({url, method: 'get-repos'})
|
||||||
|
// npub = await getId({ payload, url, method: 'get-repos' })
|
||||||
|
//
|
||||||
|
// payload = await getToken({url, method: 'get-refs', data: { repo }})
|
||||||
|
// npub = await getId({ payload, url, method: 'get-refs', data: { repo }})
|
||||||
|
// })()
|
||||||
@@ -32,6 +32,8 @@ program
|
|||||||
const name = fullPath.split(path.sep).pop()
|
const name = fullPath.split(path.sep).pop()
|
||||||
if ((home.isInitialized(name))) {
|
if ((home.isInitialized(name))) {
|
||||||
console.error(`${name} is already initialized`)
|
console.error(`${name} is already initialized`)
|
||||||
|
await git.addRemote(name)
|
||||||
|
console.log(`Added git remote for "${name}" as "pear"`)
|
||||||
process.exit(1)
|
process.exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +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 fs = require('fs')
|
const fs = require('fs')
|
||||||
|
|
||||||
@@ -39,7 +40,12 @@ swarm.on('connection', async (socket) => {
|
|||||||
store.replicate(socket)
|
store.replicate(socket)
|
||||||
const rpc = new ProtomuxRPC(socket)
|
const rpc = new ProtomuxRPC(socket)
|
||||||
|
|
||||||
const reposRes = await rpc.request('get-repos')
|
let payload = { body: { url, method: 'get-repos' } }
|
||||||
|
if (process.env.GIT_PEAR_AUTH) {
|
||||||
|
payload.header = await acl.getToken(payload.body)
|
||||||
|
}
|
||||||
|
|
||||||
|
const reposRes = await rpc.request('get-repos', Buffer.from(JSON.stringify(payload)))
|
||||||
const repositories = JSON.parse(reposRes.toString())
|
const repositories = JSON.parse(reposRes.toString())
|
||||||
if (!repositories) {
|
if (!repositories) {
|
||||||
console.error('Failed to retrieve repositories')
|
console.error('Failed to retrieve repositories')
|
||||||
@@ -65,12 +71,21 @@ swarm.on('connection', async (socket) => {
|
|||||||
|
|
||||||
await drive.core.update({ wait: true })
|
await drive.core.update({ wait: true })
|
||||||
|
|
||||||
const refsRes = await rpc.request('get-refs', Buffer.from(repoName))
|
// TODO: ACL
|
||||||
|
payload = { body: { url, method: 'get-refs', data: repoName }}
|
||||||
|
if (process.env.GIT_PEAR_AUTH) {
|
||||||
|
payload.header = await acl.getToken(payload.body)
|
||||||
|
}
|
||||||
|
const refsRes = await rpc.request('get-refs', Buffer.from(JSON.stringify(payload)))
|
||||||
|
|
||||||
await talkToGit(JSON.parse(refsRes.toString()), drive, repoName, rpc)
|
let commit
|
||||||
|
try {
|
||||||
|
commit = await git.getCommit()
|
||||||
|
} catch (e) { }
|
||||||
|
await talkToGit(JSON.parse(refsRes.toString()), drive, repoName, rpc, commit)
|
||||||
})
|
})
|
||||||
|
|
||||||
async function talkToGit (refs, drive, repoName, rpc) {
|
async function talkToGit (refs, drive, repoName, rpc, commit) {
|
||||||
process.stdin.setEncoding('utf8')
|
process.stdin.setEncoding('utf8')
|
||||||
const didFetch = false
|
const didFetch = false
|
||||||
process.stdin.on('readable', async function () {
|
process.stdin.on('readable', async function () {
|
||||||
@@ -92,22 +107,30 @@ async function talkToGit (refs, drive, repoName, rpc) {
|
|||||||
|
|
||||||
dst = dst.replace('refs/heads/', '').replace('\n\n', '')
|
dst = dst.replace('refs/heads/', '').replace('\n\n', '')
|
||||||
|
|
||||||
let command
|
let method
|
||||||
if (isDelete) {
|
if (isDelete) {
|
||||||
command = 'd-branch'
|
method = 'd-branch'
|
||||||
} else if (isForce) {
|
} else if (isForce) {
|
||||||
console.warn('To', url)
|
console.warn('To', url)
|
||||||
await git.push(src, isForce)
|
await git.push(src, isForce)
|
||||||
src = src.replace('+', '')
|
src = src.replace('+', '')
|
||||||
command = 'f-push'
|
method = 'f-push'
|
||||||
} else {
|
} else {
|
||||||
console.warn('To', url)
|
console.warn('To', url)
|
||||||
await git.push(src)
|
await git.push(src)
|
||||||
command = 'push'
|
method = 'push'
|
||||||
}
|
}
|
||||||
|
|
||||||
const publicKey = home.readPk()
|
const publicKey = home.readPk()
|
||||||
const res = await rpc.request(command, Buffer.from(`${publicKey}/${repoName}:${dst}`))
|
let payload = { body: {
|
||||||
|
url: `pear://${publicKey}/${repoName}`,
|
||||||
|
data: `${dst}#${commit}`,
|
||||||
|
method
|
||||||
|
} }
|
||||||
|
if (process.env.GIT_PEAR_AUTH) {
|
||||||
|
payload.header = await acl.getToken(payload.body)
|
||||||
|
}
|
||||||
|
const res = await rpc.request(method, Buffer.from(JSON.stringify(payload)))
|
||||||
|
|
||||||
process.stdout.write('\n\n')
|
process.stdout.write('\n\n')
|
||||||
process.exit(0)
|
process.exit(0)
|
||||||
|
|||||||
21
src/git.js
21
src/git.js
@@ -1,6 +1,25 @@
|
|||||||
const { getCodePath } = require('./home')
|
const { getCodePath } = require('./home')
|
||||||
const { spawn } = require('child_process')
|
const { spawn } = require('child_process')
|
||||||
|
|
||||||
|
async function getCommit () {
|
||||||
|
return await new Promise((resolve, reject) => {
|
||||||
|
const process = spawn('git', ['rev-parse', 'HEAD'])
|
||||||
|
let outBuffer = Buffer.from('')
|
||||||
|
process.stdout.on('data', data => {
|
||||||
|
outBuffer = Buffer.concat([outBuffer, data])
|
||||||
|
})
|
||||||
|
|
||||||
|
let errBuffer = Buffer.from('')
|
||||||
|
process.stderr.on('err', data => {
|
||||||
|
errBuffer = Buffer.concat([errBuffer, data])
|
||||||
|
})
|
||||||
|
|
||||||
|
process.on('close', code => {
|
||||||
|
return code === 0 ? resolve(outBuffer.toString().replace('\n', '')) : reject(errBuffer)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
async function lsPromise (url) {
|
async function lsPromise (url) {
|
||||||
const ls = spawn('git', ['ls-remote', url])
|
const ls = spawn('git', ['ls-remote', url])
|
||||||
const res = {}
|
const res = {}
|
||||||
@@ -182,4 +201,4 @@ async function unpackStream (packStream) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = { lsPromise, uploadPack, unpackFile, unpackStream, createBareRepo, addRemote, push }
|
module.exports = { lsPromise, uploadPack, unpackFile, unpackStream, createBareRepo, addRemote, push, getCommit }
|
||||||
|
|||||||
@@ -14,6 +14,10 @@ function shareAppFolder (name) {
|
|||||||
fs.openSync(`${APP_HOME}/${name}/.git-daemon-export-ok`, 'w')
|
fs.openSync(`${APP_HOME}/${name}/.git-daemon-export-ok`, 'w')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function shareWith (userId, branch = '*', permissions = 'rw') {
|
||||||
|
fs.appendFileSync(`${APP_HOME}/.git-daemon-export-ok`, `${userId}:${branch}:${permissions}\n`)
|
||||||
|
}
|
||||||
|
|
||||||
function unshareAppFolder (name) {
|
function unshareAppFolder (name) {
|
||||||
fs.unlinkSync(`${APP_HOME}/${name}/.git-daemon-export-ok`)
|
fs.unlinkSync(`${APP_HOME}/${name}/.git-daemon-export-ok`)
|
||||||
}
|
}
|
||||||
@@ -119,5 +123,6 @@ module.exports = {
|
|||||||
storeDaemonPid,
|
storeDaemonPid,
|
||||||
getDaemonPid,
|
getDaemonPid,
|
||||||
isDaemonRunning,
|
isDaemonRunning,
|
||||||
removeDaemonPid
|
removeDaemonPid,
|
||||||
|
shareWith,
|
||||||
}
|
}
|
||||||
|
|||||||
0
src/rpc-request.js
Normal file
0
src/rpc-request.js
Normal file
73
src/rpc.js
73
src/rpc.js
@@ -1,6 +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')
|
||||||
|
|
||||||
module.exports = class RPC {
|
module.exports = class RPC {
|
||||||
constructor (announcedRefs, repositories, drives) {
|
constructor (announcedRefs, repositories, drives) {
|
||||||
@@ -19,7 +20,7 @@ module.exports = class RPC {
|
|||||||
// which can in turn be stored in a .git-daemon-export-ok file
|
// which can in turn be stored in a .git-daemon-export-ok file
|
||||||
|
|
||||||
/* -- PULL HANDLERS -- */
|
/* -- PULL HANDLERS -- */
|
||||||
rpc.respond('get-repos', req => this.getReposHandler(req))
|
rpc.respond('get-repos', async req => await this.getReposHandler(req))
|
||||||
rpc.respond('get-refs', async req => await this.getRefsHandler(req))
|
rpc.respond('get-refs', async req => await this.getRefsHandler(req))
|
||||||
|
|
||||||
/* -- PUSH HANDLERS -- */
|
/* -- PUSH HANDLERS -- */
|
||||||
@@ -30,81 +31,87 @@ module.exports = class RPC {
|
|||||||
this.connections[peerInfo.publicKey] = rpc
|
this.connections[peerInfo.publicKey] = rpc
|
||||||
}
|
}
|
||||||
|
|
||||||
getReposHandler (_req) {
|
async getReposHandler (req) {
|
||||||
|
const { branch, url } = await this.parseReq(req)
|
||||||
|
|
||||||
const res = {}
|
const res = {}
|
||||||
for (const repo in this.repositories) {
|
for (const repoName in this.repositories) {
|
||||||
res[repo] = this.drives[repo].key.toString('hex')
|
// TODO: add only public repos and those which are shared with the peer
|
||||||
|
// Alternatively return only requested repo
|
||||||
|
res[repoName] = this.drives[repoName].key.toString('hex')
|
||||||
}
|
}
|
||||||
return Buffer.from(JSON.stringify(res))
|
return Buffer.from(JSON.stringify(res))
|
||||||
}
|
}
|
||||||
|
|
||||||
getRefsHandler (req) {
|
async getRefsHandler (req) {
|
||||||
const res = this.repositories[req.toString()]
|
const { repoName, branch, url } = await this.parseReq(req)
|
||||||
|
const res = this.repositories[repoName]
|
||||||
|
|
||||||
return Buffer.from(JSON.stringify(res))
|
return Buffer.from(JSON.stringify(res))
|
||||||
}
|
}
|
||||||
|
|
||||||
async pushHandler (req) {
|
async pushHandler (req) {
|
||||||
const { url, repo, key, branch } = this.parsePushCommand(req)
|
const { url, repoName, branch } = await this.parseReq(req)
|
||||||
// TODO: check ACL
|
|
||||||
return await new Promise((resolve, reject) => {
|
return await new Promise((resolve, reject) => {
|
||||||
const process = spawn('git', ['fetch', url, `${branch}:${branch}`], { env: { GIT_DIR: home.getCodePath(repo) } })
|
const env = { ...process.env, GIT_DIR: home.getCodePath(repoName) }
|
||||||
|
const child = spawn('git', ['fetch', url, `${branch}:${branch}`], { env })
|
||||||
let errBuffer = Buffer.from('')
|
let errBuffer = Buffer.from('')
|
||||||
process.stderr.on('data', data => {
|
child.stderr.on('data', data => {
|
||||||
errBuffer = Buffer.concat([errBuffer, data])
|
errBuffer = Buffer.concat([errBuffer, data])
|
||||||
})
|
})
|
||||||
|
|
||||||
process.on('close', code => {
|
child.on('close', code => {
|
||||||
return code === 0 ? resolve(errBuffer) : reject(errBuffer)
|
return code === 0 ? resolve(errBuffer) : reject(errBuffer)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async forcePushHandler (req) {
|
async forcePushHandler (req) {
|
||||||
const { url, repo, key, branch } = this.parsePushCommand(req)
|
const { url, repoName, branch } = await this.parseReq(req)
|
||||||
// TODO: check ACL
|
|
||||||
return await new Promise((resolve, reject) => {
|
return await new Promise((resolve, reject) => {
|
||||||
const process = spawn('git', ['fetch', url, `${branch}:${branch}`, '--force'], { env: { GIT_DIR: home.getCodePath(repo) } })
|
const env = { ...process.env, GIT_DIR: home.getCodePath(repoName) }
|
||||||
|
const child = spawn('git', ['fetch', url, `${branch}:${branch}`, '--force'], { env })
|
||||||
let errBuffer = Buffer.from('')
|
let errBuffer = Buffer.from('')
|
||||||
process.stderr.on('data', data => {
|
child.stderr.on('data', data => {
|
||||||
errBuffer = Buffer.concat([errBuffer, data])
|
errBuffer = Buffer.concat([errBuffer, data])
|
||||||
})
|
})
|
||||||
|
|
||||||
process.on('close', code => {
|
child.on('close', code => {
|
||||||
return code === 0 ? resolve(errBuffer) : reject(errBuffer)
|
return code === 0 ? resolve(errBuffer) : reject(errBuffer)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteBranchHandler (req) {
|
async deleteBranchHandler (req) {
|
||||||
const { url, repo, key, branch } = this.parsePushCommand(req)
|
const { url, repoName, branch } = await this.parseReq(req)
|
||||||
// TODO: check ACL
|
|
||||||
return await new Promise((resolve, reject) => {
|
return await new Promise((resolve, reject) => {
|
||||||
const process = spawn('git', ['branch', '-D', branch], { env: { GIT_DIR: home.getCodePath(repo) } })
|
const env = { ...process.env, GIT_DIR: home.getCodePath(repoName) }
|
||||||
|
const child = spawn('git', ['branch', '-D', branch], { env })
|
||||||
let errBuffer = Buffer.from('')
|
let errBuffer = Buffer.from('')
|
||||||
process.stderr.on('data', data => {
|
child.stderr.on('data', data => {
|
||||||
errBuffer = Buffer.concat([errBuffer, data])
|
errBuffer = Buffer.concat([errBuffer, data])
|
||||||
})
|
})
|
||||||
|
|
||||||
process.on('close', code => {
|
child.on('close', code => {
|
||||||
return code === 0 ? resolve(errBuffer) : reject(errBuffer)
|
return code === 0 ? resolve(errBuffer) : reject(errBuffer)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
parsePushCommand(req) {
|
async parseReq(req) {
|
||||||
const [url, branch] = req.toString().split(':')
|
let payload
|
||||||
const [key, repo] = url.split('/')
|
let request = JSON.parse(req.toString())
|
||||||
return {
|
if (process.env.GIT_PEAR_AUTH) {
|
||||||
url: `pear://${url}`,
|
payload = await acl.getId({
|
||||||
repo,
|
...request.body,
|
||||||
key,
|
payload: request.header
|
||||||
branch
|
})
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
loadACL(repoName) {
|
return {
|
||||||
// TODO: read contact of .git-daemon-export-ok
|
repoName: request.body.url?.split('/')?.pop(),
|
||||||
// find key and its permissions
|
branch: request.body.data?.split('#')[0],
|
||||||
|
url: request.body.url
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user