@devtion/actions 0.0.0-ed314b8 → 0.0.0-f3ea056
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.mjs +49 -83
- package/dist/index.node.js +48 -82
- package/dist/types/src/helpers/constants.d.ts +6 -0
- package/dist/types/src/helpers/constants.d.ts.map +1 -1
- package/dist/types/src/helpers/security.d.ts +2 -2
- package/dist/types/src/helpers/security.d.ts.map +1 -1
- package/dist/types/src/helpers/utils.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/helpers/constants.ts +6 -0
- package/src/helpers/security.ts +28 -50
- package/src/helpers/utils.ts +24 -37
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @module @
|
|
3
|
-
* @version 1.0.
|
|
2
|
+
* @module @devtion/actions
|
|
3
|
+
* @version 1.0.6
|
|
4
4
|
* @file A set of actions and helpers for CLI commands
|
|
5
5
|
* @copyright Ethereum Foundation 2022
|
|
6
6
|
* @license MIT
|
|
@@ -17,8 +17,7 @@ import crypto from 'crypto';
|
|
|
17
17
|
import blake from 'blakejs';
|
|
18
18
|
import { utils } from 'ffjavascript';
|
|
19
19
|
import winston from 'winston';
|
|
20
|
-
import {
|
|
21
|
-
import { pipeline, Readable } from 'stream';
|
|
20
|
+
import { pipeline } from 'stream';
|
|
22
21
|
import { promisify } from 'util';
|
|
23
22
|
import { initializeApp } from 'firebase/app';
|
|
24
23
|
import { signInWithCredential, initializeAuth, getAuth } from 'firebase/auth';
|
|
@@ -244,6 +243,12 @@ const commonTerms = {
|
|
|
244
243
|
verificationStartedAt: "verificationStartedAt"
|
|
245
244
|
}
|
|
246
245
|
},
|
|
246
|
+
avatars: {
|
|
247
|
+
name: "avatars",
|
|
248
|
+
fields: {
|
|
249
|
+
avatarUrl: "avatarUrl"
|
|
250
|
+
}
|
|
251
|
+
},
|
|
247
252
|
ceremonies: {
|
|
248
253
|
name: "ceremonies",
|
|
249
254
|
fields: {
|
|
@@ -1085,42 +1090,26 @@ const parseCeremonyFile = async (path, cleanup = false) => {
|
|
|
1085
1090
|
circuitArtifacts.push({
|
|
1086
1091
|
artifacts: artifacts
|
|
1087
1092
|
});
|
|
1088
|
-
const r1csPath = artifacts.r1csStoragePath;
|
|
1089
|
-
const wasmPath = artifacts.wasmStoragePath;
|
|
1090
1093
|
// where we storing the r1cs downloaded
|
|
1091
1094
|
const localR1csPath = `./${circuitData.name}.r1cs`;
|
|
1092
|
-
//
|
|
1093
|
-
|
|
1094
|
-
// just the correct region
|
|
1095
|
-
const s3 = new S3Client({ region: artifacts.region });
|
|
1096
|
-
try {
|
|
1097
|
-
await s3.send(new HeadObjectCommand({
|
|
1098
|
-
Bucket: artifacts.bucket,
|
|
1099
|
-
Key: r1csPath
|
|
1100
|
-
}));
|
|
1101
|
-
}
|
|
1102
|
-
catch (error) {
|
|
1103
|
-
throw new Error(`The r1cs file (${r1csPath}) seems to not exist. Please ensure this is correct and that the object is publicly available.`);
|
|
1104
|
-
}
|
|
1105
|
-
try {
|
|
1106
|
-
await s3.send(new HeadObjectCommand({
|
|
1107
|
-
Bucket: artifacts.bucket,
|
|
1108
|
-
Key: wasmPath
|
|
1109
|
-
}));
|
|
1110
|
-
}
|
|
1111
|
-
catch (error) {
|
|
1112
|
-
throw new Error(`The wasm file (${wasmPath}) seems to not exist. Please ensure this is correct and that the object is publicly available.`);
|
|
1113
|
-
}
|
|
1095
|
+
// where we storing the wasm downloaded
|
|
1096
|
+
const localWasmPath = `./${circuitData.name}.wasm`;
|
|
1114
1097
|
// download the r1cs to extract the metadata
|
|
1115
|
-
const command = new GetObjectCommand({ Bucket: artifacts.bucket, Key: artifacts.r1csStoragePath });
|
|
1116
|
-
const response = await s3.send(command);
|
|
1117
1098
|
const streamPipeline = promisify(pipeline);
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1099
|
+
// Make the call.
|
|
1100
|
+
const responseR1CS = await fetch(artifacts.r1csStoragePath);
|
|
1101
|
+
// Handle errors.
|
|
1102
|
+
if (!responseR1CS.ok && responseR1CS.status !== 200)
|
|
1103
|
+
throw new Error(`There was an error while trying to download the r1cs file for circuit ${circuitData.name}. Please check that the file has the correct permissions (public) set.`);
|
|
1104
|
+
await streamPipeline(responseR1CS.body, createWriteStream(localR1csPath));
|
|
1105
|
+
// Write the file locally
|
|
1122
1106
|
// extract the metadata from the r1cs
|
|
1123
1107
|
const metadata = getR1CSInfo(localR1csPath);
|
|
1108
|
+
// download wasm too to ensure it's available
|
|
1109
|
+
const responseWASM = await fetch(artifacts.wasmStoragePath);
|
|
1110
|
+
if (!responseWASM.ok && responseWASM.status !== 200)
|
|
1111
|
+
throw new Error(`There was an error while trying to download the WASM file for circuit ${circuitData.name}. Please check that the file has the correct permissions (public) set.`);
|
|
1112
|
+
await streamPipeline(responseWASM.body, createWriteStream(localWasmPath));
|
|
1124
1113
|
// validate that the circuit hash and template links are valid
|
|
1125
1114
|
const template = circuitData.template;
|
|
1126
1115
|
const URLMatch = template.source.match(urlPattern);
|
|
@@ -1216,9 +1205,10 @@ const parseCeremonyFile = async (path, cleanup = false) => {
|
|
|
1216
1205
|
};
|
|
1217
1206
|
}
|
|
1218
1207
|
circuits.push(circuit);
|
|
1219
|
-
// remove the local r1cs
|
|
1208
|
+
// remove the local r1cs and wasm downloads (if used for verifying the config only vs setup)
|
|
1220
1209
|
if (cleanup)
|
|
1221
1210
|
fs.unlinkSync(localR1csPath);
|
|
1211
|
+
fs.unlinkSync(localWasmPath);
|
|
1222
1212
|
}
|
|
1223
1213
|
const setupData = {
|
|
1224
1214
|
ceremonyInputData: {
|
|
@@ -2079,55 +2069,27 @@ const verifyCeremony = async (functions, firestore, ceremonyPrefix, outputDirect
|
|
|
2079
2069
|
};
|
|
2080
2070
|
|
|
2081
2071
|
/**
|
|
2082
|
-
* This function
|
|
2083
|
-
* @param user
|
|
2084
|
-
* @returns
|
|
2085
|
-
*/
|
|
2086
|
-
const getNumberOfPublicReposGitHub = async (user) => {
|
|
2087
|
-
const response = await fetch(`https://api.github.com/user/${user}/repos`, {
|
|
2088
|
-
method: "GET",
|
|
2089
|
-
headers: {
|
|
2090
|
-
Authorization: `token ${process.env.GITHUB_ACCESS_TOKEN}`
|
|
2091
|
-
}
|
|
2092
|
-
});
|
|
2093
|
-
if (response.status !== 200)
|
|
2094
|
-
throw new Error("It was not possible to retrieve the number of public repositories. Please try again.");
|
|
2095
|
-
const jsonData = await response.json();
|
|
2096
|
-
return jsonData.length;
|
|
2097
|
-
};
|
|
2098
|
-
/**
|
|
2099
|
-
* This function will return the number of followers of a user
|
|
2100
|
-
* @param user <string> The username of the user
|
|
2101
|
-
* @returns <number> The number of followers
|
|
2072
|
+
* This function queries the GitHub API to fetch users statistics
|
|
2073
|
+
* @param user {string} the user uid
|
|
2074
|
+
* @returns {any} the stats from the GitHub API
|
|
2102
2075
|
*/
|
|
2103
|
-
const
|
|
2104
|
-
const response = await fetch(`https://api.github.com/user/${user}
|
|
2076
|
+
const getGitHubStats = async (user) => {
|
|
2077
|
+
const response = await fetch(`https://api.github.com/user/${user}`, {
|
|
2105
2078
|
method: "GET",
|
|
2106
2079
|
headers: {
|
|
2107
2080
|
Authorization: `token ${process.env.GITHUB_ACCESS_TOKEN}`
|
|
2108
2081
|
}
|
|
2109
2082
|
});
|
|
2110
2083
|
if (response.status !== 200)
|
|
2111
|
-
throw new Error("It was not possible to retrieve the
|
|
2084
|
+
throw new Error("It was not possible to retrieve the user's statistic. Please try again.");
|
|
2112
2085
|
const jsonData = await response.json();
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
const getNumberOfFollowingGitHub = async (user) => {
|
|
2121
|
-
const response = await fetch(`https://api.github.com/user/${user}/following`, {
|
|
2122
|
-
method: "GET",
|
|
2123
|
-
headers: {
|
|
2124
|
-
Authorization: `token ${process.env.GITHUB_ACCESS_TOKEN}`
|
|
2125
|
-
}
|
|
2126
|
-
});
|
|
2127
|
-
if (response.status !== 200)
|
|
2128
|
-
throw new Error("It was not possible to retrieve the number of following. Please try again.");
|
|
2129
|
-
const jsonData = await response.json();
|
|
2130
|
-
return jsonData.length;
|
|
2086
|
+
const data = {
|
|
2087
|
+
following: jsonData.following,
|
|
2088
|
+
followers: jsonData.followers,
|
|
2089
|
+
publicRepos: jsonData.public_repos,
|
|
2090
|
+
avatarUrl: jsonData.avatar_url
|
|
2091
|
+
};
|
|
2092
|
+
return data;
|
|
2131
2093
|
};
|
|
2132
2094
|
/**
|
|
2133
2095
|
* This function will check if the user is reputable enough to be able to use the app
|
|
@@ -2135,19 +2097,23 @@ const getNumberOfFollowingGitHub = async (user) => {
|
|
|
2135
2097
|
* @param minimumAmountOfFollowing <number> The minimum amount of following the user should have
|
|
2136
2098
|
* @param minimumAmountOfFollowers <number> The minimum amount of followers the user should have
|
|
2137
2099
|
* @param minimumAmountOfPublicRepos <number> The minimum amount of public repos the user should have
|
|
2138
|
-
* @returns <
|
|
2100
|
+
* @returns <any> Return the avatar URL of the user if the user is reputable, false otherwise
|
|
2139
2101
|
*/
|
|
2140
2102
|
const githubReputation = async (userLogin, minimumAmountOfFollowing, minimumAmountOfFollowers, minimumAmountOfPublicRepos) => {
|
|
2141
2103
|
if (!process.env.GITHUB_ACCESS_TOKEN)
|
|
2142
2104
|
throw new Error("The GitHub access token is missing. Please insert a valid token to be used for anti-sybil checks on user registation, and then try again.");
|
|
2143
|
-
const following = await
|
|
2144
|
-
const repos = await getNumberOfPublicReposGitHub(userLogin);
|
|
2145
|
-
const followers = await getNumberOfFollowersGitHub(userLogin);
|
|
2105
|
+
const { following, followers, publicRepos, avatarUrl } = await getGitHubStats(userLogin);
|
|
2146
2106
|
if (following < minimumAmountOfFollowing ||
|
|
2147
|
-
|
|
2107
|
+
publicRepos < minimumAmountOfPublicRepos ||
|
|
2148
2108
|
followers < minimumAmountOfFollowers)
|
|
2149
|
-
return
|
|
2150
|
-
|
|
2109
|
+
return {
|
|
2110
|
+
reputable: false,
|
|
2111
|
+
avatarUrl: ""
|
|
2112
|
+
};
|
|
2113
|
+
return {
|
|
2114
|
+
reputable: true,
|
|
2115
|
+
avatarUrl: avatarUrl
|
|
2116
|
+
};
|
|
2151
2117
|
};
|
|
2152
2118
|
|
|
2153
2119
|
/**
|
package/dist/index.node.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @module @
|
|
3
|
-
* @version 1.0.
|
|
2
|
+
* @module @devtion/actions
|
|
3
|
+
* @version 1.0.6
|
|
4
4
|
* @file A set of actions and helpers for CLI commands
|
|
5
5
|
* @copyright Ethereum Foundation 2022
|
|
6
6
|
* @license MIT
|
|
@@ -19,7 +19,6 @@ var crypto = require('crypto');
|
|
|
19
19
|
var blake = require('blakejs');
|
|
20
20
|
var ffjavascript = require('ffjavascript');
|
|
21
21
|
var winston = require('winston');
|
|
22
|
-
var clientS3 = require('@aws-sdk/client-s3');
|
|
23
22
|
var stream = require('stream');
|
|
24
23
|
var util = require('util');
|
|
25
24
|
var app = require('firebase/app');
|
|
@@ -246,6 +245,12 @@ const commonTerms = {
|
|
|
246
245
|
verificationStartedAt: "verificationStartedAt"
|
|
247
246
|
}
|
|
248
247
|
},
|
|
248
|
+
avatars: {
|
|
249
|
+
name: "avatars",
|
|
250
|
+
fields: {
|
|
251
|
+
avatarUrl: "avatarUrl"
|
|
252
|
+
}
|
|
253
|
+
},
|
|
249
254
|
ceremonies: {
|
|
250
255
|
name: "ceremonies",
|
|
251
256
|
fields: {
|
|
@@ -1087,42 +1092,26 @@ const parseCeremonyFile = async (path, cleanup = false) => {
|
|
|
1087
1092
|
circuitArtifacts.push({
|
|
1088
1093
|
artifacts: artifacts
|
|
1089
1094
|
});
|
|
1090
|
-
const r1csPath = artifacts.r1csStoragePath;
|
|
1091
|
-
const wasmPath = artifacts.wasmStoragePath;
|
|
1092
1095
|
// where we storing the r1cs downloaded
|
|
1093
1096
|
const localR1csPath = `./${circuitData.name}.r1cs`;
|
|
1094
|
-
//
|
|
1095
|
-
|
|
1096
|
-
// just the correct region
|
|
1097
|
-
const s3 = new clientS3.S3Client({ region: artifacts.region });
|
|
1098
|
-
try {
|
|
1099
|
-
await s3.send(new clientS3.HeadObjectCommand({
|
|
1100
|
-
Bucket: artifacts.bucket,
|
|
1101
|
-
Key: r1csPath
|
|
1102
|
-
}));
|
|
1103
|
-
}
|
|
1104
|
-
catch (error) {
|
|
1105
|
-
throw new Error(`The r1cs file (${r1csPath}) seems to not exist. Please ensure this is correct and that the object is publicly available.`);
|
|
1106
|
-
}
|
|
1107
|
-
try {
|
|
1108
|
-
await s3.send(new clientS3.HeadObjectCommand({
|
|
1109
|
-
Bucket: artifacts.bucket,
|
|
1110
|
-
Key: wasmPath
|
|
1111
|
-
}));
|
|
1112
|
-
}
|
|
1113
|
-
catch (error) {
|
|
1114
|
-
throw new Error(`The wasm file (${wasmPath}) seems to not exist. Please ensure this is correct and that the object is publicly available.`);
|
|
1115
|
-
}
|
|
1097
|
+
// where we storing the wasm downloaded
|
|
1098
|
+
const localWasmPath = `./${circuitData.name}.wasm`;
|
|
1116
1099
|
// download the r1cs to extract the metadata
|
|
1117
|
-
const command = new clientS3.GetObjectCommand({ Bucket: artifacts.bucket, Key: artifacts.r1csStoragePath });
|
|
1118
|
-
const response = await s3.send(command);
|
|
1119
1100
|
const streamPipeline = util.promisify(stream.pipeline);
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1101
|
+
// Make the call.
|
|
1102
|
+
const responseR1CS = await fetch(artifacts.r1csStoragePath);
|
|
1103
|
+
// Handle errors.
|
|
1104
|
+
if (!responseR1CS.ok && responseR1CS.status !== 200)
|
|
1105
|
+
throw new Error(`There was an error while trying to download the r1cs file for circuit ${circuitData.name}. Please check that the file has the correct permissions (public) set.`);
|
|
1106
|
+
await streamPipeline(responseR1CS.body, fs.createWriteStream(localR1csPath));
|
|
1107
|
+
// Write the file locally
|
|
1124
1108
|
// extract the metadata from the r1cs
|
|
1125
1109
|
const metadata = getR1CSInfo(localR1csPath);
|
|
1110
|
+
// download wasm too to ensure it's available
|
|
1111
|
+
const responseWASM = await fetch(artifacts.wasmStoragePath);
|
|
1112
|
+
if (!responseWASM.ok && responseWASM.status !== 200)
|
|
1113
|
+
throw new Error(`There was an error while trying to download the WASM file for circuit ${circuitData.name}. Please check that the file has the correct permissions (public) set.`);
|
|
1114
|
+
await streamPipeline(responseWASM.body, fs.createWriteStream(localWasmPath));
|
|
1126
1115
|
// validate that the circuit hash and template links are valid
|
|
1127
1116
|
const template = circuitData.template;
|
|
1128
1117
|
const URLMatch = template.source.match(urlPattern);
|
|
@@ -1218,9 +1207,10 @@ const parseCeremonyFile = async (path, cleanup = false) => {
|
|
|
1218
1207
|
};
|
|
1219
1208
|
}
|
|
1220
1209
|
circuits.push(circuit);
|
|
1221
|
-
// remove the local r1cs
|
|
1210
|
+
// remove the local r1cs and wasm downloads (if used for verifying the config only vs setup)
|
|
1222
1211
|
if (cleanup)
|
|
1223
1212
|
fs.unlinkSync(localR1csPath);
|
|
1213
|
+
fs.unlinkSync(localWasmPath);
|
|
1224
1214
|
}
|
|
1225
1215
|
const setupData = {
|
|
1226
1216
|
ceremonyInputData: {
|
|
@@ -2081,55 +2071,27 @@ const verifyCeremony = async (functions, firestore$1, ceremonyPrefix, outputDire
|
|
|
2081
2071
|
};
|
|
2082
2072
|
|
|
2083
2073
|
/**
|
|
2084
|
-
* This function
|
|
2085
|
-
* @param user
|
|
2086
|
-
* @returns
|
|
2087
|
-
*/
|
|
2088
|
-
const getNumberOfPublicReposGitHub = async (user) => {
|
|
2089
|
-
const response = await fetch(`https://api.github.com/user/${user}/repos`, {
|
|
2090
|
-
method: "GET",
|
|
2091
|
-
headers: {
|
|
2092
|
-
Authorization: `token ${process.env.GITHUB_ACCESS_TOKEN}`
|
|
2093
|
-
}
|
|
2094
|
-
});
|
|
2095
|
-
if (response.status !== 200)
|
|
2096
|
-
throw new Error("It was not possible to retrieve the number of public repositories. Please try again.");
|
|
2097
|
-
const jsonData = await response.json();
|
|
2098
|
-
return jsonData.length;
|
|
2099
|
-
};
|
|
2100
|
-
/**
|
|
2101
|
-
* This function will return the number of followers of a user
|
|
2102
|
-
* @param user <string> The username of the user
|
|
2103
|
-
* @returns <number> The number of followers
|
|
2074
|
+
* This function queries the GitHub API to fetch users statistics
|
|
2075
|
+
* @param user {string} the user uid
|
|
2076
|
+
* @returns {any} the stats from the GitHub API
|
|
2104
2077
|
*/
|
|
2105
|
-
const
|
|
2106
|
-
const response = await fetch(`https://api.github.com/user/${user}
|
|
2078
|
+
const getGitHubStats = async (user) => {
|
|
2079
|
+
const response = await fetch(`https://api.github.com/user/${user}`, {
|
|
2107
2080
|
method: "GET",
|
|
2108
2081
|
headers: {
|
|
2109
2082
|
Authorization: `token ${process.env.GITHUB_ACCESS_TOKEN}`
|
|
2110
2083
|
}
|
|
2111
2084
|
});
|
|
2112
2085
|
if (response.status !== 200)
|
|
2113
|
-
throw new Error("It was not possible to retrieve the
|
|
2086
|
+
throw new Error("It was not possible to retrieve the user's statistic. Please try again.");
|
|
2114
2087
|
const jsonData = await response.json();
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
const getNumberOfFollowingGitHub = async (user) => {
|
|
2123
|
-
const response = await fetch(`https://api.github.com/user/${user}/following`, {
|
|
2124
|
-
method: "GET",
|
|
2125
|
-
headers: {
|
|
2126
|
-
Authorization: `token ${process.env.GITHUB_ACCESS_TOKEN}`
|
|
2127
|
-
}
|
|
2128
|
-
});
|
|
2129
|
-
if (response.status !== 200)
|
|
2130
|
-
throw new Error("It was not possible to retrieve the number of following. Please try again.");
|
|
2131
|
-
const jsonData = await response.json();
|
|
2132
|
-
return jsonData.length;
|
|
2088
|
+
const data = {
|
|
2089
|
+
following: jsonData.following,
|
|
2090
|
+
followers: jsonData.followers,
|
|
2091
|
+
publicRepos: jsonData.public_repos,
|
|
2092
|
+
avatarUrl: jsonData.avatar_url
|
|
2093
|
+
};
|
|
2094
|
+
return data;
|
|
2133
2095
|
};
|
|
2134
2096
|
/**
|
|
2135
2097
|
* This function will check if the user is reputable enough to be able to use the app
|
|
@@ -2137,19 +2099,23 @@ const getNumberOfFollowingGitHub = async (user) => {
|
|
|
2137
2099
|
* @param minimumAmountOfFollowing <number> The minimum amount of following the user should have
|
|
2138
2100
|
* @param minimumAmountOfFollowers <number> The minimum amount of followers the user should have
|
|
2139
2101
|
* @param minimumAmountOfPublicRepos <number> The minimum amount of public repos the user should have
|
|
2140
|
-
* @returns <
|
|
2102
|
+
* @returns <any> Return the avatar URL of the user if the user is reputable, false otherwise
|
|
2141
2103
|
*/
|
|
2142
2104
|
const githubReputation = async (userLogin, minimumAmountOfFollowing, minimumAmountOfFollowers, minimumAmountOfPublicRepos) => {
|
|
2143
2105
|
if (!process.env.GITHUB_ACCESS_TOKEN)
|
|
2144
2106
|
throw new Error("The GitHub access token is missing. Please insert a valid token to be used for anti-sybil checks on user registation, and then try again.");
|
|
2145
|
-
const following = await
|
|
2146
|
-
const repos = await getNumberOfPublicReposGitHub(userLogin);
|
|
2147
|
-
const followers = await getNumberOfFollowersGitHub(userLogin);
|
|
2107
|
+
const { following, followers, publicRepos, avatarUrl } = await getGitHubStats(userLogin);
|
|
2148
2108
|
if (following < minimumAmountOfFollowing ||
|
|
2149
|
-
|
|
2109
|
+
publicRepos < minimumAmountOfPublicRepos ||
|
|
2150
2110
|
followers < minimumAmountOfFollowers)
|
|
2151
|
-
return
|
|
2152
|
-
|
|
2111
|
+
return {
|
|
2112
|
+
reputable: false,
|
|
2113
|
+
avatarUrl: ""
|
|
2114
|
+
};
|
|
2115
|
+
return {
|
|
2116
|
+
reputable: true,
|
|
2117
|
+
avatarUrl: avatarUrl
|
|
2118
|
+
};
|
|
2153
2119
|
};
|
|
2154
2120
|
|
|
2155
2121
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../../src/helpers/constants.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,sBAAsB,+CAA+C,CAAA;AAElF,eAAO,MAAM,mBAAmB,6BAA6B,CAAA;AAE7D,eAAO,MAAM,gBAAgB,UAAU,CAAA;AAEvC,eAAO,MAAM,gBAAgB,KAAK,CAAA;AAElC,eAAO,MAAM,eAAe,UAAU,CAAA;AAEtC,eAAO,MAAM,sBAAsB,UAAU,CAAA;AAE7C,eAAO,MAAM,sBAAsB,SAAS,CAAA;AAE5C,eAAO,MAAM,4BAA4B,aAAa,CAAA;AAEtD,eAAO,MAAM,cAAc,sBAAsB,CAAA;AAEjD,eAAO,MAAM,yBAAyB,iBAAiB,CAAA;AAEvD;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2ChC,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,gBAAgB;;;GA6G5B,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,WAAW
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../../src/helpers/constants.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,sBAAsB,+CAA+C,CAAA;AAElF,eAAO,MAAM,mBAAmB,6BAA6B,CAAA;AAE7D,eAAO,MAAM,gBAAgB,UAAU,CAAA;AAEvC,eAAO,MAAM,gBAAgB,KAAK,CAAA;AAElC,eAAO,MAAM,eAAe,UAAU,CAAA;AAEtC,eAAO,MAAM,sBAAsB,UAAU,CAAA;AAE7C,eAAO,MAAM,sBAAsB,SAAS,CAAA;AAE5C,eAAO,MAAM,4BAA4B,aAAa,CAAA;AAEtD,eAAO,MAAM,cAAc,sBAAsB,CAAA;AAEjD,eAAO,MAAM,yBAAyB,iBAAiB,CAAA;AAEvD;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2ChC,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,gBAAgB;;;GA6G5B,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6HvB,CAAA"}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @param minimumAmountOfFollowing <number> The minimum amount of following the user should have
|
|
5
5
|
* @param minimumAmountOfFollowers <number> The minimum amount of followers the user should have
|
|
6
6
|
* @param minimumAmountOfPublicRepos <number> The minimum amount of public repos the user should have
|
|
7
|
-
* @returns <
|
|
7
|
+
* @returns <any> Return the avatar URL of the user if the user is reputable, false otherwise
|
|
8
8
|
*/
|
|
9
|
-
export declare const githubReputation: (userLogin: string, minimumAmountOfFollowing: number, minimumAmountOfFollowers: number, minimumAmountOfPublicRepos: number) => Promise<
|
|
9
|
+
export declare const githubReputation: (userLogin: string, minimumAmountOfFollowing: number, minimumAmountOfFollowers: number, minimumAmountOfPublicRepos: number) => Promise<any>;
|
|
10
10
|
//# sourceMappingURL=security.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"security.d.ts","sourceRoot":"","sources":["../../../../src/helpers/security.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"security.d.ts","sourceRoot":"","sources":["../../../../src/helpers/security.ts"],"names":[],"mappings":"AA4BA;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,cACd,MAAM,4BACS,MAAM,4BACN,MAAM,8BACJ,MAAM,KACnC,QAAQ,GAAG,CAsBb,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../src/helpers/utils.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAC9C,OAAW,EAAE,YAAY,
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../src/helpers/utils.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAC9C,OAAW,EAAE,YAAY,EAAqB,MAAM,IAAI,CAAA;AAExD,OAAO,OAAO,EAAE,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAEzC,OAAO,EACH,eAAe,EACf,YAAY,EAGZ,oBAAoB,EACpB,oBAAoB,EACpB,iBAAiB,EAGpB,MAAM,gBAAgB,CAAA;AAmBvB;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,SAAgB,MAAM,YAAW,OAAO,KAAW,QAAQ,iBAAiB,CAuNzG,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,+BAA+B,iBAAkB,MAAM,UAAU,MAAM,KAAG,MAgBtF,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,oCAAoC,gBAAiB,MAAM,WAAW,MAAM,WAUxF,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,eAAe,aAAc,MAAM,KAAG,MASlD,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,wBAAyB,MAAM,KAAG,MACH,CAAA;AAElE;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,QAAS,MAAM,KAAG,MAEsC,CAAA;AAElF;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,cAAsE,CAAA;AAEtG;;;;;;;GAOG;AACH,eAAO,MAAM,4BAA4B,aAC3B,MAAM,oBAAoB,CAAC,oBACnB,MAAM,KACzB,oBAYF,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,cAAe,MAAM,WAAW,OAAO,KAAG,MAC1B,CAAA;AAEjD;;;;;;;;GAQG;AACH,eAAO,MAAM,sCAAsC,sBAC5B,SAAS,YAClB,MAAM,oBAAoB,CAAC,cACzB,MAAM,iBACH,MAAM,gBACP,OAAO,KACtB,QAAQ,MAAM,oBAAoB,CAAC,CAmCrC,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,0CAA0C,0BAC5B,MAAM,gBACf,MAAM,gBACN,OAAO,WAImF,CAAA;AAE5G;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,qCAAqC,sBAC3B,SAAS,YAClB,MAAM,oBAAoB,CAAC,cACzB,MAAM,iBACH,MAAM,4BACK,MAAM,YAAY,CAAC,yBACtB,MAAM,gBACf,MAAM,gBACN,OAAO,KACtB,QAAQ,MAAM,CA2DhB,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,aAAc,MAAM,UAAS,QAAQ,aAAa,CAAC,OAAO,CAAC,KAAY,MAQvG,CAAA;AAEN;;;;;;;GAOG;AACH,eAAO,MAAM,iBAAiB,kBACX,MAAM,UACb,MAAM,UACN,MAAM,YACJ,YAAY,KACvB,MAYF,CAAA;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,WAAW,sBAAuB,MAAM,KAAG,eA0IvD,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,WAAY,MAAM,KAAG,MAA0D,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devtion/actions",
|
|
3
|
-
"version": "0.0.0-
|
|
3
|
+
"version": "0.0.0-f3ea056",
|
|
4
4
|
"description": "A set of actions and helpers for CLI commands",
|
|
5
5
|
"repository": "git@github.com:privacy-scaling-explorations/p0tion.git",
|
|
6
6
|
"homepage": "https://github.com/privacy-scaling-explorations/p0tion",
|
|
@@ -83,5 +83,5 @@
|
|
|
83
83
|
"publishConfig": {
|
|
84
84
|
"access": "public"
|
|
85
85
|
},
|
|
86
|
-
"gitHead": "
|
|
86
|
+
"gitHead": "7abc6a0bd781de4a52c12f6b557f27a579291a41"
|
|
87
87
|
}
|
package/src/helpers/constants.ts
CHANGED
package/src/helpers/security.ts
CHANGED
|
@@ -1,57 +1,29 @@
|
|
|
1
1
|
import fetch from "@adobe/node-fetch-retry"
|
|
2
2
|
/**
|
|
3
|
-
* This function
|
|
4
|
-
* @param user
|
|
5
|
-
* @returns
|
|
3
|
+
* This function queries the GitHub API to fetch users statistics
|
|
4
|
+
* @param user {string} the user uid
|
|
5
|
+
* @returns {any} the stats from the GitHub API
|
|
6
6
|
*/
|
|
7
|
-
const
|
|
8
|
-
const response = await fetch(`https://api.github.com/user/${user}
|
|
7
|
+
const getGitHubStats = async (user: string): Promise<any> => {
|
|
8
|
+
const response = await fetch(`https://api.github.com/user/${user}`, {
|
|
9
9
|
method: "GET",
|
|
10
10
|
headers: {
|
|
11
11
|
Authorization: `token ${process.env.GITHUB_ACCESS_TOKEN!}`
|
|
12
12
|
}
|
|
13
13
|
})
|
|
14
14
|
if (response.status !== 200)
|
|
15
|
-
throw new Error("It was not possible to retrieve the
|
|
16
|
-
const jsonData: any = await response.json()
|
|
17
|
-
return jsonData.length
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* This function will return the number of followers of a user
|
|
21
|
-
* @param user <string> The username of the user
|
|
22
|
-
* @returns <number> The number of followers
|
|
23
|
-
*/
|
|
24
|
-
const getNumberOfFollowersGitHub = async (user: string): Promise<number> => {
|
|
25
|
-
const response = await fetch(`https://api.github.com/user/${user}/followers`, {
|
|
26
|
-
method: "GET",
|
|
27
|
-
headers: {
|
|
28
|
-
Authorization: `token ${process.env.GITHUB_ACCESS_TOKEN!}`
|
|
29
|
-
}
|
|
30
|
-
})
|
|
31
|
-
if (response.status !== 200)
|
|
32
|
-
throw new Error("It was not possible to retrieve the number of followers. Please try again.")
|
|
33
|
-
const jsonData: any = await response.json()
|
|
34
|
-
return jsonData.length
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* This function will return the number of following of a user
|
|
38
|
-
* @param user <string> The username of the user
|
|
39
|
-
* @returns <number> The number of following users
|
|
40
|
-
*/
|
|
41
|
-
const getNumberOfFollowingGitHub = async (user: string): Promise<number> => {
|
|
42
|
-
const response = await fetch(`https://api.github.com/user/${user}/following`, {
|
|
43
|
-
method: "GET",
|
|
44
|
-
headers: {
|
|
45
|
-
Authorization: `token ${process.env.GITHUB_ACCESS_TOKEN!}`
|
|
46
|
-
}
|
|
47
|
-
})
|
|
48
|
-
|
|
49
|
-
if (response.status !== 200)
|
|
50
|
-
throw new Error("It was not possible to retrieve the number of following. Please try again.")
|
|
15
|
+
throw new Error("It was not possible to retrieve the user's statistic. Please try again.")
|
|
51
16
|
|
|
52
17
|
const jsonData: any = await response.json()
|
|
53
18
|
|
|
54
|
-
|
|
19
|
+
const data = {
|
|
20
|
+
following: jsonData.following,
|
|
21
|
+
followers: jsonData.followers,
|
|
22
|
+
publicRepos: jsonData.public_repos,
|
|
23
|
+
avatarUrl: jsonData.avatar_url
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return data
|
|
55
27
|
}
|
|
56
28
|
|
|
57
29
|
/**
|
|
@@ -60,27 +32,33 @@ const getNumberOfFollowingGitHub = async (user: string): Promise<number> => {
|
|
|
60
32
|
* @param minimumAmountOfFollowing <number> The minimum amount of following the user should have
|
|
61
33
|
* @param minimumAmountOfFollowers <number> The minimum amount of followers the user should have
|
|
62
34
|
* @param minimumAmountOfPublicRepos <number> The minimum amount of public repos the user should have
|
|
63
|
-
* @returns <
|
|
35
|
+
* @returns <any> Return the avatar URL of the user if the user is reputable, false otherwise
|
|
64
36
|
*/
|
|
65
37
|
export const githubReputation = async (
|
|
66
38
|
userLogin: string,
|
|
67
39
|
minimumAmountOfFollowing: number,
|
|
68
40
|
minimumAmountOfFollowers: number,
|
|
69
41
|
minimumAmountOfPublicRepos: number
|
|
70
|
-
): Promise<
|
|
42
|
+
): Promise<any> => {
|
|
71
43
|
if (!process.env.GITHUB_ACCESS_TOKEN)
|
|
72
44
|
throw new Error(
|
|
73
45
|
"The GitHub access token is missing. Please insert a valid token to be used for anti-sybil checks on user registation, and then try again."
|
|
74
46
|
)
|
|
75
|
-
|
|
76
|
-
const
|
|
77
|
-
const followers = await getNumberOfFollowersGitHub(userLogin)
|
|
47
|
+
|
|
48
|
+
const { following, followers, publicRepos, avatarUrl } = await getGitHubStats(userLogin)
|
|
78
49
|
|
|
79
50
|
if (
|
|
80
51
|
following < minimumAmountOfFollowing ||
|
|
81
|
-
|
|
52
|
+
publicRepos < minimumAmountOfPublicRepos ||
|
|
82
53
|
followers < minimumAmountOfFollowers
|
|
83
54
|
)
|
|
84
|
-
return
|
|
85
|
-
|
|
55
|
+
return {
|
|
56
|
+
reputable: false,
|
|
57
|
+
avatarUrl: ""
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return {
|
|
61
|
+
reputable: true,
|
|
62
|
+
avatarUrl: avatarUrl
|
|
63
|
+
}
|
|
86
64
|
}
|
package/src/helpers/utils.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Firestore } from "firebase/firestore"
|
|
2
|
-
import fs, { ReadPosition } from "fs"
|
|
2
|
+
import fs, { ReadPosition, createWriteStream } from "fs"
|
|
3
3
|
import { utils as ffUtils } from "ffjavascript"
|
|
4
4
|
import winston, { Logger } from "winston"
|
|
5
|
-
import
|
|
5
|
+
import fetch from "@adobe/node-fetch-retry"
|
|
6
6
|
import {
|
|
7
7
|
CircuitMetadata,
|
|
8
8
|
Contribution,
|
|
@@ -29,7 +29,7 @@ import {
|
|
|
29
29
|
getZkeyStorageFilePath
|
|
30
30
|
} from "./storage"
|
|
31
31
|
import { blake512FromPath } from "./crypto"
|
|
32
|
-
import {
|
|
32
|
+
import { pipeline } from "stream"
|
|
33
33
|
import { promisify } from "util"
|
|
34
34
|
|
|
35
35
|
/**
|
|
@@ -87,49 +87,34 @@ export const parseCeremonyFile = async (path: string, cleanup: boolean = false):
|
|
|
87
87
|
circuitArtifacts.push({
|
|
88
88
|
artifacts: artifacts
|
|
89
89
|
})
|
|
90
|
-
const r1csPath = artifacts.r1csStoragePath
|
|
91
|
-
const wasmPath = artifacts.wasmStoragePath
|
|
92
90
|
|
|
93
91
|
// where we storing the r1cs downloaded
|
|
94
92
|
const localR1csPath = `./${circuitData.name}.r1cs`
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
// we don't need any privileges to download this
|
|
98
|
-
// just the correct region
|
|
99
|
-
const s3 = new S3Client({region: artifacts.region})
|
|
100
|
-
|
|
101
|
-
try {
|
|
102
|
-
await s3.send(new HeadObjectCommand({
|
|
103
|
-
Bucket: artifacts.bucket,
|
|
104
|
-
Key: r1csPath
|
|
105
|
-
}))
|
|
106
|
-
} catch (error: any) {
|
|
107
|
-
throw new Error(`The r1cs file (${r1csPath}) seems to not exist. Please ensure this is correct and that the object is publicly available.`)
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
try {
|
|
111
|
-
await s3.send(new HeadObjectCommand({
|
|
112
|
-
Bucket: artifacts.bucket,
|
|
113
|
-
Key: wasmPath
|
|
114
|
-
}))
|
|
115
|
-
} catch (error: any) {
|
|
116
|
-
throw new Error(`The wasm file (${wasmPath}) seems to not exist. Please ensure this is correct and that the object is publicly available.`)
|
|
117
|
-
}
|
|
93
|
+
// where we storing the wasm downloaded
|
|
94
|
+
const localWasmPath = `./${circuitData.name}.wasm`
|
|
118
95
|
|
|
119
96
|
// download the r1cs to extract the metadata
|
|
120
|
-
const command = new GetObjectCommand({ Bucket: artifacts.bucket, Key: artifacts.r1csStoragePath })
|
|
121
|
-
const response = await s3.send(command)
|
|
122
97
|
const streamPipeline = promisify(pipeline)
|
|
123
98
|
|
|
124
|
-
|
|
125
|
-
|
|
99
|
+
// Make the call.
|
|
100
|
+
const responseR1CS = await fetch(artifacts.r1csStoragePath)
|
|
126
101
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
102
|
+
// Handle errors.
|
|
103
|
+
if (!responseR1CS.ok && responseR1CS.status !== 200)
|
|
104
|
+
throw new Error(`There was an error while trying to download the r1cs file for circuit ${circuitData.name}. Please check that the file has the correct permissions (public) set.`)
|
|
105
|
+
|
|
106
|
+
await streamPipeline(responseR1CS.body!, createWriteStream(localR1csPath))
|
|
107
|
+
// Write the file locally
|
|
108
|
+
|
|
130
109
|
// extract the metadata from the r1cs
|
|
131
110
|
const metadata = getR1CSInfo(localR1csPath)
|
|
132
111
|
|
|
112
|
+
// download wasm too to ensure it's available
|
|
113
|
+
const responseWASM = await fetch(artifacts.wasmStoragePath)
|
|
114
|
+
if (!responseWASM.ok && responseWASM.status !== 200)
|
|
115
|
+
throw new Error(`There was an error while trying to download the WASM file for circuit ${circuitData.name}. Please check that the file has the correct permissions (public) set.`)
|
|
116
|
+
await streamPipeline(responseWASM.body!, createWriteStream(localWasmPath))
|
|
117
|
+
|
|
133
118
|
// validate that the circuit hash and template links are valid
|
|
134
119
|
const template = circuitData.template
|
|
135
120
|
|
|
@@ -244,8 +229,10 @@ export const parseCeremonyFile = async (path: string, cleanup: boolean = false):
|
|
|
244
229
|
|
|
245
230
|
circuits.push(circuit)
|
|
246
231
|
|
|
247
|
-
// remove the local r1cs
|
|
248
|
-
if (cleanup)
|
|
232
|
+
// remove the local r1cs and wasm downloads (if used for verifying the config only vs setup)
|
|
233
|
+
if (cleanup)
|
|
234
|
+
fs.unlinkSync(localR1csPath)
|
|
235
|
+
fs.unlinkSync(localWasmPath)
|
|
249
236
|
}
|
|
250
237
|
|
|
251
238
|
const setupData: SetupCeremonyData = {
|