25 Commits

Author SHA1 Message Date
157d2dee49 3.4.0 2019-08-31 13:42:50 +02:00
590ca961a6 Merge pull request #45 from 67P/docs/github-signup
Add GitHub signup oracle documentation
2019-08-31 13:26:23 +02:00
6476fe5c88 Improve signup docs 2019-08-31 13:23:11 +02:00
101e35622a Add GitHub signup oracle documentation 2019-08-31 12:52:36 +02:00
afa67e5ac7 Prefix all configuration environment variables
The convention here is to prefix all Kredit related configuration
variables with `KREDITS_`
2019-08-31 12:51:44 +02:00
cbbc6c359e Merge pull request #41 from 67P/feature/github-signup
Add GitHub signup oracle
2019-08-28 15:56:54 +02:00
c16ea51769 Error handling for fetching Github access token 2019-08-27 18:35:40 +02:00
fc49213b01 Update contracts min version 2019-08-27 18:23:22 +02:00
32dc6a7358 GitHub signup fixes
* Don't fail when profile has no name set
* Use scope that can only read public profile information (no scope)
* Better error handling
2019-08-27 18:22:36 +02:00
53dee63a76 Add env variable for session secret 2019-08-27 15:30:30 +02:00
97ec6ce9bc Add KREDITS_DAO_ADDRESS to readme 2019-08-27 15:22:38 +02:00
342a5cd829 Add gasLimit option when adding contributor 2019-08-27 13:16:43 +02:00
45064df737 Fix wrong logger function call 2019-08-27 12:57:36 +02:00
d9a9ad7793 Update deps
Fixes security vulns
2019-08-27 12:51:31 +02:00
d65e92e1fe Merge branch 'master' into feature/github-signup 2019-08-27 12:39:15 +02:00
0fff3b1db0 Merge pull request #43 from 67P/feature/custom_dao_address
Add ENV var for custom DAO address
2019-08-27 12:38:45 +02:00
1f1053e289 Remove apm address from options
It's already the default in the contracts module.
2019-08-27 12:37:50 +02:00
84f20efff0 Add ENV var for custom DAO address
This makes it much easier to test hubot-kredits with local development
chains.
2019-08-27 12:19:01 +02:00
cd8343516f 3.3.1 2019-08-14 15:42:23 +02:00
Greg Karékinian
41c5903cf5 Merge pull request #42 from 67P/chore/mediawiki_small_threshold
Change threshold for small wiki contributions
2019-08-14 12:51:48 +02:00
9a4dc43aa5 Change threshold for small wiki contributions
Turns out 280 is a bit low. Let's try 500 instead.
2019-08-14 12:46:19 +02:00
082bf4848d Minor changes 2019-07-26 20:50:36 +02:00
41dd813eaf Replace custom CORS header solution with middleware 2019-07-26 20:48:20 +02:00
b35cbcc63a Finish implementation of GitHub signup oracle 2019-07-26 04:15:11 +02:00
137e9eb4ed Add initial implementation of the GitHub signup oracle 2019-07-11 15:44:58 +02:00
6 changed files with 998 additions and 255 deletions

View File

@@ -10,9 +10,29 @@ contributions.
## Setup ## Setup
### Ethereum wallet
You will need an Ethereum wallet for your bot, so it can interact with the You will need an Ethereum wallet for your bot, so it can interact with the
Ethereum smart contracts. `npm run create-wallet` will do the job for you. Ethereum smart contracts. `npm run create-wallet` will do the job for you.
The wallet must be funded with enough ETH to interact with the contracts.
### Contract permissions
The bot wallet needs the following Aragon contract permissions to interact
with [kredits-contracts]:
1. `ADD_CONTRIBUTION_ROLE` on the `Contribution` contract
2. `MANAGE_CONTRIBUTORS_ROLE` on the `Contributor` contract
These permissions can be configured using the [Aragon
CLI](https://hack.aragon.org/docs/cli-intro.html) (see [kredits-contracts].
aragon dao acl grant [DAO address] [contribution app address] ADD_CONTRIBUTION_ROLE [bot wallet address]
aragon dao acl grant [DAO address] [contributor app address] MANAGE_CONTRIBUTORS_ROLE [bot wallet address]
To get the `Contribution` and `Contributor` app addresses use `aragon dao apps`.
## Configuration ## Configuration
As usual in Hubot, you can add all config as environment variables. As usual in Hubot, you can add all config as environment variables.
@@ -24,6 +44,11 @@ As usual in Hubot, you can add all config as environment variables.
| `KREDITS_WALLET_PATH` | Path to an Etherum wallet JSON file (default: `./wallet.json`) | | `KREDITS_WALLET_PATH` | Path to an Etherum wallet JSON file (default: `./wallet.json`) |
| `KREDITS_WALLET_PASSWORD` | Wallet password | | `KREDITS_WALLET_PASSWORD` | Wallet password |
| `KREDITS_PROVIDER_URL` | Ethereum JSON-RPC URL (default: `http://localhost:7545`) | | `KREDITS_PROVIDER_URL` | Ethereum JSON-RPC URL (default: `http://localhost:7545`) |
| `KREDITS_WEB_URL` | URL of the Kredits Web app (default: `https://kredits.kosmos.org`) |
| `KREDITS_DAO_ADDRESS` | DAO Kernel address |
| `KREDITS_SESSION_SECRET` | Secret used by [grant](https://www.npmjs.com/package/grant) to sign the session ID |
| `KREDITS_GRANT_HOST` | Host used by [grant](https://www.npmjs.com/package/grant) to generate OAuth redirect URLs (default: `localhost:8888`) |
| `KREDITS_GRANT_PROTOCOL` | Protocol (http or https) used by [grant](https://www.npmjs.com/package/grant") to generate the OAuth redirect URLs (default: "http") |
## Integrations ## Integrations
@@ -34,6 +59,12 @@ which carry a kredits label: `kredits-1`, `kredits-2`, `kredits-3` for small,
medium and large contributions. If there are multiple people assigned, it will medium and large contributions. If there are multiple people assigned, it will
issue contribution tokens for all of them. issue contribution tokens for all of them.
If `KREDITS_GITHUB_KEY` and `KREDITS_GITHUB_SECRET` are set, the bot will also
expose OAuth endpoints to authenticate new contributors and register new
contributor profiles on the smart contract. For this feature, a [GitHub OAuth
app] is required and the [OAuth grant config variables](#Configuration) must be
set.
#### Setup #### Setup
Point a GitHub organization webhook to the following URL: Point a GitHub organization webhook to the following URL:
@@ -45,6 +76,8 @@ Point a GitHub organization webhook to the following URL:
| Key | Description | | Key | Description |
| --- | --- | | --- | --- |
| `KREDITS_GITHUB_REPO_BLACKLIST` | Repos which you do not want to issue kredits for. Format: `orgname/reponame`, e.g. `67P/test-one-two` | | `KREDITS_GITHUB_REPO_BLACKLIST` | Repos which you do not want to issue kredits for. Format: `orgname/reponame`, e.g. `67P/test-one-two` |
| `KREDITS_GITHUB_KEY` | Key of the [GitHub OAuth app] used to authenticate contributors |
| `KREDITS_GITHUB_SECRET` | Secret of the [GitHub OAuth app] used to authenticate contributors |
### Gitea ### Gitea
@@ -80,3 +113,6 @@ wiki's API on its own.
| Key | Description | | Key | Description |
| --- | --- | | --- | --- |
| `KREDITS_MEDIAWIKI_URL` | Your wiki URL, e.g. `https://wiki.kosmos.org/` | | `KREDITS_MEDIAWIKI_URL` | Your wiki URL, e.g. `https://wiki.kosmos.org/` |
[kredits-contracts]: https://github.com/67P/kredits-contracts
[GitHub OAuth app]: https://developer.github.com/apps/about-apps/#about-oauth-apps

View File

@@ -7,6 +7,7 @@ const Kredits = require('kredits-contracts');
const walletPath = process.env.KREDITS_WALLET_PATH || './wallet.json'; const walletPath = process.env.KREDITS_WALLET_PATH || './wallet.json';
const walletJson = fs.readFileSync(walletPath); const walletJson = fs.readFileSync(walletPath);
const providerUrl = process.env.KREDITS_PROVIDER_URL; const providerUrl = process.env.KREDITS_PROVIDER_URL;
const daoAddress = process.env.KREDITS_DAO_ADDRESS;
const ipfsConfig = { const ipfsConfig = {
host: process.env.IPFS_API_HOST || 'localhost', host: process.env.IPFS_API_HOST || 'localhost',
@@ -48,14 +49,14 @@ module.exports = async function(robot) {
// Kredits contracts setup // Kredits contracts setup
// //
const opts = { ipfsConfig };
if (daoAddress) {
opts.addresses = { Kernel: daoAddress };
}
let kredits; let kredits;
try { try {
kredits = await new Kredits(signer.provider, signer, { kredits = await new Kredits(signer.provider, signer, opts).init();
// TODO support local devchain custom address
apm: 'open.aragonpm.eth',
// addresses: { Kernel: '0x93aa4531329e4bf3efcd1ec0b74adb6f66d9d10e' }
ipfsConfig
}).init();
} catch(error) { } catch(error) {
robot.logger.warning('[hubot-kredits] Could not set up kredits:', error); robot.logger.warning('[hubot-kredits] Could not set up kredits:', error);
process.exit(1); process.exit(1);

View File

@@ -1,5 +1,8 @@
const util = require('util'); const util = require('util');
const fetch = require('node-fetch'); const fetch = require('node-fetch');
const session = require('express-session');
const grant = require('grant-express');
const cors = require('cors');
const amountFromLabels = require('./utils/amount-from-labels'); const amountFromLabels = require('./utils/amount-from-labels');
const kindFromLabels = require('./utils/kind-from-labels'); const kindFromLabels = require('./utils/kind-from-labels');
@@ -21,6 +24,8 @@ module.exports = async function(robot, kredits) {
robot.logger.debug('[hubot-kredits] Ignoring GitHub actions from ', util.inspect(repoBlackList)); robot.logger.debug('[hubot-kredits] Ignoring GitHub actions from ', util.inspect(repoBlackList));
} }
const kreditsWebUrl = process.env.KREDITS_WEB_URL || 'https://kredits.kosmos.org';
const Contributor = kredits.Contributor; const Contributor = kredits.Contributor;
const Contribution = kredits.Contribution; const Contribution = kredits.Contribution;
@@ -172,4 +177,95 @@ module.exports = async function(robot, kredits) {
} }
}); });
//
// GitHub signup
//
if (process.env.KREDITS_GITHUB_KEY && process.env.KREDITS_GITHUB_SECRET) {
const grantConfig = {
defaults: {
protocol: (process.env.KREDITS_GRANT_PROTOCOL || "http"),
host: (process.env.KREDITS_GRANT_HOST || 'localhost:8888'),
transport: 'session',
response: 'tokens',
path: '/kredits/signup'
},
github: {
key: process.env.KREDITS_GITHUB_KEY,
secret: process.env.KREDITS_GITHUB_SECRET,
callback: '/kredits/signup/github'
}
};
robot.router.use(session({ secret: process.env.KREDITS_SESSION_SECRET || 'grant' }));
robot.router.use('/kredits/signup', grant(grantConfig));
robot.router.get('/kredits/signup/github', async (req, res) => {
const access_token = req.session.grant.response.access_token;
res.redirect(`${kreditsWebUrl}/signup/github#access_token=${access_token}`);
});
robot.router.options('/kredits/signup/github', cors());
robot.router.post('/kredits/signup/github', cors(), async (req, res) => {
const accessToken = req.body.accessToken;
if (!accessToken) {
res.status(400).json({});
return;
}
try {
const githubResponse = await fetch('https://api.github.com/user', {
headers: {
'Accept': 'application/vnd.github.v3+json',
'Authorization': `token ${accessToken}`
}
});
} catch (error) {
robot.logger.error('[hubot-kredits] Fetching user data from GitHub failed:', error);
res.status(500).json({ error });
};
if (githubResponse.status >= 300) {
res.status(githubResponse.status).json({});
return;
}
const user = await githubResponse.json();
const contributor = await kredits.Contributor.findByAccount({
site: 'github.com',
username: user.login
});
if (!contributor) {
let contributorAttr = {};
contributorAttr.account = req.body.account;
contributorAttr.name = user.name || user.login;
contributorAttr.kind = "person";
contributorAttr.url = user.blog;
contributorAttr.github_username = user.login;
contributorAttr.github_uid = user.id;
kredits.Contributor.add(contributorAttr, { gasLimit: 350000 })
.then(transaction => {
robot.logger.info('[hubot-kredits] Contributor added from GitHub signup', transaction.hash);
res.status(201);
res.json({
transactionHash: transaction.hash,
github_username: user.login
});
}, error => {
robot.logger.error(`[hubot-kredits] Adding contributor failed: ${error}`);
res.status(422);
res.json({ error })
});
} else {
res.json({
github_username: user.login
});
}
});
} else {
robot.logger.warning('[hubot-kredits] No KREDITS_GITHUB_KEY and KREDITS_GITHUB_SECRET configured for OAuth signup');
}
}; };

View File

@@ -129,8 +129,7 @@ module.exports = async function(robot, kredits) {
function calculateAmountForChanges(details) { function calculateAmountForChanges(details) {
let amount; let amount;
if (details.charsAdded < 280) { if (details.charsAdded < 500) {
// less than a tweet
amount = 500; amount = 500;
} else if (details.charsAdded < 2000) { } else if (details.charsAdded < 2000) {
amount = 1500; amount = 1500;

1095
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{ {
"name": "hubot-kredits", "name": "hubot-kredits",
"version": "3.3.0", "version": "3.4.0",
"description": "Kosmos Kredits functionality for chat bots", "description": "Kosmos Kredits functionality for chat bots",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
@@ -10,11 +10,15 @@
"create-wallet": "scripts/create-wallet.js" "create-wallet": "scripts/create-wallet.js"
}, },
"dependencies": { "dependencies": {
"cors": "^2.8.5",
"eth-provider": "^0.2.2", "eth-provider": "^0.2.2",
"ethers": "^4.0.27", "ethers": "^4.0.27",
"group-array": "^0.3.3", "express": "^4.17.1",
"express-session": "^1.16.2",
"grant-express": "^4.6.1",
"group-array": "^1.0.0",
"kosmos-schemas": "^1.1.2", "kosmos-schemas": "^1.1.2",
"kredits-contracts": "^5.3.0", "kredits-contracts": "^5.4.0",
"node-cron": "^2.0.3", "node-cron": "^2.0.3",
"node-fetch": "^2.3.0", "node-fetch": "^2.3.0",
"prompt": "^1.0.0" "prompt": "^1.0.0"