@devtion/actions 0.0.0-7e983e3 → 0.0.0-9614e0c
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 +47 -73
- package/dist/index.node.js +46 -72
- 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 +29 -49
- package/src/helpers/utils.ts +17 -22
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,7 +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 { S3Client,
|
|
20
|
+
import { S3Client, GetObjectCommand } from '@aws-sdk/client-s3';
|
|
21
21
|
import { pipeline, Readable } from 'stream';
|
|
22
22
|
import { promisify } from 'util';
|
|
23
23
|
import { initializeApp } from 'firebase/app';
|
|
@@ -244,6 +244,12 @@ const commonTerms = {
|
|
|
244
244
|
verificationStartedAt: "verificationStartedAt"
|
|
245
245
|
}
|
|
246
246
|
},
|
|
247
|
+
avatars: {
|
|
248
|
+
name: "avatars",
|
|
249
|
+
fields: {
|
|
250
|
+
avatarUrl: "avatarUrl"
|
|
251
|
+
}
|
|
252
|
+
},
|
|
247
253
|
ceremonies: {
|
|
248
254
|
name: "ceremonies",
|
|
249
255
|
fields: {
|
|
@@ -1085,42 +1091,34 @@ const parseCeremonyFile = async (path, cleanup = false) => {
|
|
|
1085
1091
|
circuitArtifacts.push({
|
|
1086
1092
|
artifacts: artifacts
|
|
1087
1093
|
});
|
|
1088
|
-
const r1csPath = artifacts.r1csStoragePath;
|
|
1089
|
-
const wasmPath = artifacts.wasmStoragePath;
|
|
1090
1094
|
// where we storing the r1cs downloaded
|
|
1091
1095
|
const localR1csPath = `./${circuitData.name}.r1cs`;
|
|
1096
|
+
// where we storing the wasm downloaded
|
|
1097
|
+
const localWasmPath = `./${circuitData.name}.wasm`;
|
|
1092
1098
|
// check that the artifacts exist in S3
|
|
1093
1099
|
// we don't need any privileges to download this
|
|
1094
1100
|
// just the correct region
|
|
1095
|
-
const s3 = new S3Client({
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
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
|
-
}
|
|
1101
|
+
const s3 = new S3Client({
|
|
1102
|
+
region: artifacts.region,
|
|
1103
|
+
credentials: undefined
|
|
1104
|
+
});
|
|
1114
1105
|
// download the r1cs to extract the metadata
|
|
1115
1106
|
const command = new GetObjectCommand({ Bucket: artifacts.bucket, Key: artifacts.r1csStoragePath });
|
|
1116
1107
|
const response = await s3.send(command);
|
|
1117
1108
|
const streamPipeline = promisify(pipeline);
|
|
1118
1109
|
if (response.$metadata.httpStatusCode !== 200)
|
|
1119
|
-
throw new Error(
|
|
1110
|
+
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.`);
|
|
1120
1111
|
if (response.Body instanceof Readable)
|
|
1121
1112
|
await streamPipeline(response.Body, fs.createWriteStream(localR1csPath));
|
|
1122
1113
|
// extract the metadata from the r1cs
|
|
1123
1114
|
const metadata = getR1CSInfo(localR1csPath);
|
|
1115
|
+
// download wasm too to ensure it's available
|
|
1116
|
+
const wasmCommand = new GetObjectCommand({ Bucket: artifacts.bucket, Key: artifacts.wasmStoragePath });
|
|
1117
|
+
const wasmResponse = await s3.send(wasmCommand);
|
|
1118
|
+
if (wasmResponse.$metadata.httpStatusCode !== 200)
|
|
1119
|
+
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.`);
|
|
1120
|
+
if (wasmResponse.Body instanceof Readable)
|
|
1121
|
+
await streamPipeline(wasmResponse.Body, fs.createWriteStream(localWasmPath));
|
|
1124
1122
|
// validate that the circuit hash and template links are valid
|
|
1125
1123
|
const template = circuitData.template;
|
|
1126
1124
|
const URLMatch = template.source.match(urlPattern);
|
|
@@ -2079,55 +2077,27 @@ const verifyCeremony = async (functions, firestore, ceremonyPrefix, outputDirect
|
|
|
2079
2077
|
};
|
|
2080
2078
|
|
|
2081
2079
|
/**
|
|
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
|
|
2080
|
+
* This function queries the GitHub API to fetch users statistics
|
|
2081
|
+
* @param user {string} the user uid
|
|
2082
|
+
* @returns {any} the stats from the GitHub API
|
|
2102
2083
|
*/
|
|
2103
|
-
const
|
|
2104
|
-
const response = await fetch(`https://api.github.com/user/${user}
|
|
2084
|
+
const getGitHubStats = async (user) => {
|
|
2085
|
+
const response = await fetch(`https://api.github.com/user/${user}`, {
|
|
2105
2086
|
method: "GET",
|
|
2106
2087
|
headers: {
|
|
2107
2088
|
Authorization: `token ${process.env.GITHUB_ACCESS_TOKEN}`
|
|
2108
2089
|
}
|
|
2109
2090
|
});
|
|
2110
2091
|
if (response.status !== 200)
|
|
2111
|
-
throw new Error("It was not possible to retrieve the
|
|
2092
|
+
throw new Error("It was not possible to retrieve the user's statistic. Please try again.");
|
|
2112
2093
|
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;
|
|
2094
|
+
const data = {
|
|
2095
|
+
following: jsonData.following,
|
|
2096
|
+
followers: jsonData.followers,
|
|
2097
|
+
publicRepos: jsonData.public_repos,
|
|
2098
|
+
avatarUrl: jsonData.avatar_url
|
|
2099
|
+
};
|
|
2100
|
+
return data;
|
|
2131
2101
|
};
|
|
2132
2102
|
/**
|
|
2133
2103
|
* This function will check if the user is reputable enough to be able to use the app
|
|
@@ -2135,19 +2105,23 @@ const getNumberOfFollowingGitHub = async (user) => {
|
|
|
2135
2105
|
* @param minimumAmountOfFollowing <number> The minimum amount of following the user should have
|
|
2136
2106
|
* @param minimumAmountOfFollowers <number> The minimum amount of followers the user should have
|
|
2137
2107
|
* @param minimumAmountOfPublicRepos <number> The minimum amount of public repos the user should have
|
|
2138
|
-
* @returns <
|
|
2108
|
+
* @returns <any> Return the avatar URL of the user if the user is reputable, false otherwise
|
|
2139
2109
|
*/
|
|
2140
2110
|
const githubReputation = async (userLogin, minimumAmountOfFollowing, minimumAmountOfFollowers, minimumAmountOfPublicRepos) => {
|
|
2141
2111
|
if (!process.env.GITHUB_ACCESS_TOKEN)
|
|
2142
2112
|
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);
|
|
2113
|
+
const { following, followers, publicRepos, avatarUrl } = await getGitHubStats(userLogin);
|
|
2146
2114
|
if (following < minimumAmountOfFollowing ||
|
|
2147
|
-
|
|
2115
|
+
publicRepos < minimumAmountOfPublicRepos ||
|
|
2148
2116
|
followers < minimumAmountOfFollowers)
|
|
2149
|
-
return
|
|
2150
|
-
|
|
2117
|
+
return {
|
|
2118
|
+
reputable: false,
|
|
2119
|
+
avatarUrl: ""
|
|
2120
|
+
};
|
|
2121
|
+
return {
|
|
2122
|
+
reputable: true,
|
|
2123
|
+
avatarUrl: avatarUrl
|
|
2124
|
+
};
|
|
2151
2125
|
};
|
|
2152
2126
|
|
|
2153
2127
|
/**
|
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
|
|
@@ -246,6 +246,12 @@ const commonTerms = {
|
|
|
246
246
|
verificationStartedAt: "verificationStartedAt"
|
|
247
247
|
}
|
|
248
248
|
},
|
|
249
|
+
avatars: {
|
|
250
|
+
name: "avatars",
|
|
251
|
+
fields: {
|
|
252
|
+
avatarUrl: "avatarUrl"
|
|
253
|
+
}
|
|
254
|
+
},
|
|
249
255
|
ceremonies: {
|
|
250
256
|
name: "ceremonies",
|
|
251
257
|
fields: {
|
|
@@ -1087,42 +1093,34 @@ const parseCeremonyFile = async (path, cleanup = false) => {
|
|
|
1087
1093
|
circuitArtifacts.push({
|
|
1088
1094
|
artifacts: artifacts
|
|
1089
1095
|
});
|
|
1090
|
-
const r1csPath = artifacts.r1csStoragePath;
|
|
1091
|
-
const wasmPath = artifacts.wasmStoragePath;
|
|
1092
1096
|
// where we storing the r1cs downloaded
|
|
1093
1097
|
const localR1csPath = `./${circuitData.name}.r1cs`;
|
|
1098
|
+
// where we storing the wasm downloaded
|
|
1099
|
+
const localWasmPath = `./${circuitData.name}.wasm`;
|
|
1094
1100
|
// check that the artifacts exist in S3
|
|
1095
1101
|
// we don't need any privileges to download this
|
|
1096
1102
|
// just the correct region
|
|
1097
|
-
const s3 = new clientS3.S3Client({
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
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
|
-
}
|
|
1103
|
+
const s3 = new clientS3.S3Client({
|
|
1104
|
+
region: artifacts.region,
|
|
1105
|
+
credentials: undefined
|
|
1106
|
+
});
|
|
1116
1107
|
// download the r1cs to extract the metadata
|
|
1117
1108
|
const command = new clientS3.GetObjectCommand({ Bucket: artifacts.bucket, Key: artifacts.r1csStoragePath });
|
|
1118
1109
|
const response = await s3.send(command);
|
|
1119
1110
|
const streamPipeline = util.promisify(stream.pipeline);
|
|
1120
1111
|
if (response.$metadata.httpStatusCode !== 200)
|
|
1121
|
-
throw new Error(
|
|
1112
|
+
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.`);
|
|
1122
1113
|
if (response.Body instanceof stream.Readable)
|
|
1123
1114
|
await streamPipeline(response.Body, fs.createWriteStream(localR1csPath));
|
|
1124
1115
|
// extract the metadata from the r1cs
|
|
1125
1116
|
const metadata = getR1CSInfo(localR1csPath);
|
|
1117
|
+
// download wasm too to ensure it's available
|
|
1118
|
+
const wasmCommand = new clientS3.GetObjectCommand({ Bucket: artifacts.bucket, Key: artifacts.wasmStoragePath });
|
|
1119
|
+
const wasmResponse = await s3.send(wasmCommand);
|
|
1120
|
+
if (wasmResponse.$metadata.httpStatusCode !== 200)
|
|
1121
|
+
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.`);
|
|
1122
|
+
if (wasmResponse.Body instanceof stream.Readable)
|
|
1123
|
+
await streamPipeline(wasmResponse.Body, fs.createWriteStream(localWasmPath));
|
|
1126
1124
|
// validate that the circuit hash and template links are valid
|
|
1127
1125
|
const template = circuitData.template;
|
|
1128
1126
|
const URLMatch = template.source.match(urlPattern);
|
|
@@ -2081,55 +2079,27 @@ const verifyCeremony = async (functions, firestore$1, ceremonyPrefix, outputDire
|
|
|
2081
2079
|
};
|
|
2082
2080
|
|
|
2083
2081
|
/**
|
|
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
|
|
2082
|
+
* This function queries the GitHub API to fetch users statistics
|
|
2083
|
+
* @param user {string} the user uid
|
|
2084
|
+
* @returns {any} the stats from the GitHub API
|
|
2104
2085
|
*/
|
|
2105
|
-
const
|
|
2106
|
-
const response = await fetch(`https://api.github.com/user/${user}
|
|
2086
|
+
const getGitHubStats = async (user) => {
|
|
2087
|
+
const response = await fetch(`https://api.github.com/user/${user}`, {
|
|
2107
2088
|
method: "GET",
|
|
2108
2089
|
headers: {
|
|
2109
2090
|
Authorization: `token ${process.env.GITHUB_ACCESS_TOKEN}`
|
|
2110
2091
|
}
|
|
2111
2092
|
});
|
|
2112
2093
|
if (response.status !== 200)
|
|
2113
|
-
throw new Error("It was not possible to retrieve the
|
|
2094
|
+
throw new Error("It was not possible to retrieve the user's statistic. Please try again.");
|
|
2114
2095
|
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;
|
|
2096
|
+
const data = {
|
|
2097
|
+
following: jsonData.following,
|
|
2098
|
+
followers: jsonData.followers,
|
|
2099
|
+
publicRepos: jsonData.public_repos,
|
|
2100
|
+
avatarUrl: jsonData.avatar_url
|
|
2101
|
+
};
|
|
2102
|
+
return data;
|
|
2133
2103
|
};
|
|
2134
2104
|
/**
|
|
2135
2105
|
* This function will check if the user is reputable enough to be able to use the app
|
|
@@ -2137,19 +2107,23 @@ const getNumberOfFollowingGitHub = async (user) => {
|
|
|
2137
2107
|
* @param minimumAmountOfFollowing <number> The minimum amount of following the user should have
|
|
2138
2108
|
* @param minimumAmountOfFollowers <number> The minimum amount of followers the user should have
|
|
2139
2109
|
* @param minimumAmountOfPublicRepos <number> The minimum amount of public repos the user should have
|
|
2140
|
-
* @returns <
|
|
2110
|
+
* @returns <any> Return the avatar URL of the user if the user is reputable, false otherwise
|
|
2141
2111
|
*/
|
|
2142
2112
|
const githubReputation = async (userLogin, minimumAmountOfFollowing, minimumAmountOfFollowers, minimumAmountOfPublicRepos) => {
|
|
2143
2113
|
if (!process.env.GITHUB_ACCESS_TOKEN)
|
|
2144
2114
|
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);
|
|
2115
|
+
const { following, followers, publicRepos, avatarUrl } = await getGitHubStats(userLogin);
|
|
2148
2116
|
if (following < minimumAmountOfFollowing ||
|
|
2149
|
-
|
|
2117
|
+
publicRepos < minimumAmountOfPublicRepos ||
|
|
2150
2118
|
followers < minimumAmountOfFollowers)
|
|
2151
|
-
return
|
|
2152
|
-
|
|
2119
|
+
return {
|
|
2120
|
+
reputable: false,
|
|
2121
|
+
avatarUrl: ""
|
|
2122
|
+
};
|
|
2123
|
+
return {
|
|
2124
|
+
reputable: true,
|
|
2125
|
+
avatarUrl: avatarUrl
|
|
2126
|
+
};
|
|
2153
2127
|
};
|
|
2154
2128
|
|
|
2155
2129
|
/**
|
|
@@ -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":"AA8BA;;;;;;;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,EAAE,MAAM,IAAI,CAAA;AAErC,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,
|
|
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,EAAE,MAAM,IAAI,CAAA;AAErC,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,CA+NzG,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-9614e0c",
|
|
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": "61b8937938f16a4a92a0468a0ba7ec8306188a60"
|
|
87
87
|
}
|
package/src/helpers/constants.ts
CHANGED
package/src/helpers/security.ts
CHANGED
|
@@ -1,45 +1,12 @@
|
|
|
1
1
|
import fetch from "@adobe/node-fetch-retry"
|
|
2
|
+
|
|
2
3
|
/**
|
|
3
|
-
* This function
|
|
4
|
-
* @param user
|
|
5
|
-
* @returns
|
|
6
|
-
*/
|
|
7
|
-
const getNumberOfPublicReposGitHub = async (user: string): Promise<number> => {
|
|
8
|
-
const response = await fetch(`https://api.github.com/user/${user}/repos`, {
|
|
9
|
-
method: "GET",
|
|
10
|
-
headers: {
|
|
11
|
-
Authorization: `token ${process.env.GITHUB_ACCESS_TOKEN!}`
|
|
12
|
-
}
|
|
13
|
-
})
|
|
14
|
-
if (response.status !== 200)
|
|
15
|
-
throw new Error("It was not possible to retrieve the number of public repositories. Please try again.")
|
|
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
|
|
4
|
+
* This function queries the GitHub API to fetch users statistics
|
|
5
|
+
* @param user {string} the user uid
|
|
6
|
+
* @returns {any} the stats from the GitHub API
|
|
40
7
|
*/
|
|
41
|
-
const
|
|
42
|
-
const response = await fetch(`https://api.github.com/user/${user}
|
|
8
|
+
const getGitHubStats = async (user: string): Promise<any> => {
|
|
9
|
+
const response = await fetch(`https://api.github.com/user/${user}`, {
|
|
43
10
|
method: "GET",
|
|
44
11
|
headers: {
|
|
45
12
|
Authorization: `token ${process.env.GITHUB_ACCESS_TOKEN!}`
|
|
@@ -47,11 +14,18 @@ const getNumberOfFollowingGitHub = async (user: string): Promise<number> => {
|
|
|
47
14
|
})
|
|
48
15
|
|
|
49
16
|
if (response.status !== 200)
|
|
50
|
-
throw new Error("It was not possible to retrieve the
|
|
17
|
+
throw new Error("It was not possible to retrieve the user's statistic. Please try again.")
|
|
51
18
|
|
|
52
19
|
const jsonData: any = await response.json()
|
|
53
20
|
|
|
54
|
-
|
|
21
|
+
const data = {
|
|
22
|
+
following: jsonData.following,
|
|
23
|
+
followers: jsonData.followers,
|
|
24
|
+
publicRepos: jsonData.public_repos,
|
|
25
|
+
avatarUrl: jsonData.avatar_url
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return data
|
|
55
29
|
}
|
|
56
30
|
|
|
57
31
|
/**
|
|
@@ -60,27 +34,33 @@ const getNumberOfFollowingGitHub = async (user: string): Promise<number> => {
|
|
|
60
34
|
* @param minimumAmountOfFollowing <number> The minimum amount of following the user should have
|
|
61
35
|
* @param minimumAmountOfFollowers <number> The minimum amount of followers the user should have
|
|
62
36
|
* @param minimumAmountOfPublicRepos <number> The minimum amount of public repos the user should have
|
|
63
|
-
* @returns <
|
|
37
|
+
* @returns <any> Return the avatar URL of the user if the user is reputable, false otherwise
|
|
64
38
|
*/
|
|
65
39
|
export const githubReputation = async (
|
|
66
40
|
userLogin: string,
|
|
67
41
|
minimumAmountOfFollowing: number,
|
|
68
42
|
minimumAmountOfFollowers: number,
|
|
69
43
|
minimumAmountOfPublicRepos: number
|
|
70
|
-
): Promise<
|
|
44
|
+
): Promise<any> => {
|
|
71
45
|
if (!process.env.GITHUB_ACCESS_TOKEN)
|
|
72
46
|
throw new Error(
|
|
73
47
|
"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
48
|
)
|
|
75
|
-
|
|
76
|
-
const
|
|
77
|
-
const followers = await getNumberOfFollowersGitHub(userLogin)
|
|
49
|
+
|
|
50
|
+
const { following, followers, publicRepos, avatarUrl } = await getGitHubStats(userLogin)
|
|
78
51
|
|
|
79
52
|
if (
|
|
80
53
|
following < minimumAmountOfFollowing ||
|
|
81
|
-
|
|
54
|
+
publicRepos < minimumAmountOfPublicRepos ||
|
|
82
55
|
followers < minimumAmountOfFollowers
|
|
83
56
|
)
|
|
84
|
-
return
|
|
85
|
-
|
|
57
|
+
return {
|
|
58
|
+
reputable: false,
|
|
59
|
+
avatarUrl: ""
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return {
|
|
63
|
+
reputable: true,
|
|
64
|
+
avatarUrl: avatarUrl
|
|
65
|
+
}
|
|
86
66
|
}
|
package/src/helpers/utils.ts
CHANGED
|
@@ -87,34 +87,19 @@ 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`
|
|
93
|
+
// where we storing the wasm downloaded
|
|
94
|
+
const localWasmPath = `./${circuitData.name}.wasm`
|
|
95
95
|
|
|
96
96
|
// check that the artifacts exist in S3
|
|
97
97
|
// we don't need any privileges to download this
|
|
98
98
|
// just the correct region
|
|
99
|
-
const s3 = new S3Client({
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
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
|
-
}
|
|
99
|
+
const s3 = new S3Client({
|
|
100
|
+
region: artifacts.region,
|
|
101
|
+
credentials: undefined
|
|
102
|
+
})
|
|
118
103
|
|
|
119
104
|
// download the r1cs to extract the metadata
|
|
120
105
|
const command = new GetObjectCommand({ Bucket: artifacts.bucket, Key: artifacts.r1csStoragePath })
|
|
@@ -122,7 +107,7 @@ export const parseCeremonyFile = async (path: string, cleanup: boolean = false):
|
|
|
122
107
|
const streamPipeline = promisify(pipeline)
|
|
123
108
|
|
|
124
109
|
if (response.$metadata.httpStatusCode !== 200)
|
|
125
|
-
throw new Error(
|
|
110
|
+
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.`)
|
|
126
111
|
|
|
127
112
|
if (response.Body instanceof Readable)
|
|
128
113
|
await streamPipeline(response.Body, fs.createWriteStream(localR1csPath))
|
|
@@ -130,6 +115,16 @@ export const parseCeremonyFile = async (path: string, cleanup: boolean = false):
|
|
|
130
115
|
// extract the metadata from the r1cs
|
|
131
116
|
const metadata = getR1CSInfo(localR1csPath)
|
|
132
117
|
|
|
118
|
+
// download wasm too to ensure it's available
|
|
119
|
+
const wasmCommand = new GetObjectCommand({ Bucket: artifacts.bucket, Key: artifacts.wasmStoragePath })
|
|
120
|
+
const wasmResponse = await s3.send(wasmCommand)
|
|
121
|
+
|
|
122
|
+
if (wasmResponse.$metadata.httpStatusCode !== 200)
|
|
123
|
+
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.`)
|
|
124
|
+
|
|
125
|
+
if (wasmResponse.Body instanceof Readable)
|
|
126
|
+
await streamPipeline(wasmResponse.Body, fs.createWriteStream(localWasmPath))
|
|
127
|
+
|
|
133
128
|
// validate that the circuit hash and template links are valid
|
|
134
129
|
const template = circuitData.template
|
|
135
130
|
|