Merge pull request #130 from gmgale/bot

Bot - Started Github integration
This commit is contained in:
BlackMagiq
2022-12-21 17:11:41 -05:00
committed by GitHub
14 changed files with 1380 additions and 658 deletions
+408
View File
@@ -10,9 +10,11 @@
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@godaddy/terminus": "^4.11.2", "@godaddy/terminus": "^4.11.2",
"@octokit/rest": "^19.0.5",
"@sentry/node": "^7.14.0", "@sentry/node": "^7.14.0",
"@sentry/tracing": "^7.19.0", "@sentry/tracing": "^7.19.0",
"@types/crypto-js": "^4.1.1", "@types/crypto-js": "^4.1.1",
"@types/libsodium-wrappers": "^0.7.10",
"axios": "^1.1.3", "axios": "^1.1.3",
"bigint-conversion": "^2.2.2", "bigint-conversion": "^2.2.2",
"cookie-parser": "^1.4.6", "cookie-parser": "^1.4.6",
@@ -26,6 +28,7 @@
"helmet": "^5.1.1", "helmet": "^5.1.1",
"jsonwebtoken": "^8.5.1", "jsonwebtoken": "^8.5.1",
"jsrp": "^0.2.4", "jsrp": "^0.2.4",
"libsodium-wrappers": "^0.7.10",
"mongoose": "^6.7.2", "mongoose": "^6.7.2",
"nodemailer": "^6.8.0", "nodemailer": "^6.8.0",
"posthog-node": "^2.1.0", "posthog-node": "^2.1.0",
@@ -2590,6 +2593,153 @@
"node": ">= 8" "node": ">= 8"
} }
}, },
"node_modules/@octokit/auth-token": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-3.0.2.tgz",
"integrity": "sha512-pq7CwIMV1kmzkFTimdwjAINCXKTajZErLB4wMLYapR2nuB/Jpr66+05wOTZMSCBXP6n4DdDWT2W19Bm17vU69Q==",
"dependencies": {
"@octokit/types": "^8.0.0"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/@octokit/core": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.1.0.tgz",
"integrity": "sha512-Czz/59VefU+kKDy+ZfDwtOIYIkFjExOKf+HA92aiTZJ6EfWpFzYQWw0l54ji8bVmyhc+mGaLUbSUmXazG7z5OQ==",
"dependencies": {
"@octokit/auth-token": "^3.0.0",
"@octokit/graphql": "^5.0.0",
"@octokit/request": "^6.0.0",
"@octokit/request-error": "^3.0.0",
"@octokit/types": "^8.0.0",
"before-after-hook": "^2.2.0",
"universal-user-agent": "^6.0.0"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/@octokit/endpoint": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-7.0.3.tgz",
"integrity": "sha512-57gRlb28bwTsdNXq+O3JTQ7ERmBTuik9+LelgcLIVfYwf235VHbN9QNo4kXExtp/h8T423cR5iJThKtFYxC7Lw==",
"dependencies": {
"@octokit/types": "^8.0.0",
"is-plain-object": "^5.0.0",
"universal-user-agent": "^6.0.0"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/@octokit/graphql": {
"version": "5.0.4",
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-5.0.4.tgz",
"integrity": "sha512-amO1M5QUQgYQo09aStR/XO7KAl13xpigcy/kI8/N1PnZYSS69fgte+xA4+c2DISKqUZfsh0wwjc2FaCt99L41A==",
"dependencies": {
"@octokit/request": "^6.0.0",
"@octokit/types": "^8.0.0",
"universal-user-agent": "^6.0.0"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/@octokit/openapi-types": {
"version": "14.0.0",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-14.0.0.tgz",
"integrity": "sha512-HNWisMYlR8VCnNurDU6os2ikx0s0VyEjDYHNS/h4cgb8DeOxQ0n72HyinUtdDVxJhFy3FWLGl0DJhfEWk3P5Iw=="
},
"node_modules/@octokit/plugin-paginate-rest": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-5.0.1.tgz",
"integrity": "sha512-7A+rEkS70pH36Z6JivSlR7Zqepz3KVucEFVDnSrgHXzG7WLAzYwcHZbKdfTXHwuTHbkT1vKvz7dHl1+HNf6Qyw==",
"dependencies": {
"@octokit/types": "^8.0.0"
},
"engines": {
"node": ">= 14"
},
"peerDependencies": {
"@octokit/core": ">=4"
}
},
"node_modules/@octokit/plugin-request-log": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz",
"integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==",
"peerDependencies": {
"@octokit/core": ">=3"
}
},
"node_modules/@octokit/plugin-rest-endpoint-methods": {
"version": "6.7.0",
"resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-6.7.0.tgz",
"integrity": "sha512-orxQ0fAHA7IpYhG2flD2AygztPlGYNAdlzYz8yrD8NDgelPfOYoRPROfEyIe035PlxvbYrgkfUZIhSBKju/Cvw==",
"dependencies": {
"@octokit/types": "^8.0.0",
"deprecation": "^2.3.1"
},
"engines": {
"node": ">= 14"
},
"peerDependencies": {
"@octokit/core": ">=3"
}
},
"node_modules/@octokit/request": {
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.2.tgz",
"integrity": "sha512-6VDqgj0HMc2FUX2awIs+sM6OwLgwHvAi4KCK3mT2H2IKRt6oH9d0fej5LluF5mck1lRR/rFWN0YIDSYXYSylbw==",
"dependencies": {
"@octokit/endpoint": "^7.0.0",
"@octokit/request-error": "^3.0.0",
"@octokit/types": "^8.0.0",
"is-plain-object": "^5.0.0",
"node-fetch": "^2.6.7",
"universal-user-agent": "^6.0.0"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/@octokit/request-error": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-3.0.2.tgz",
"integrity": "sha512-WMNOFYrSaX8zXWoJg9u/pKgWPo94JXilMLb2VManNOby9EZxrQaBe/QSC4a1TzpAlpxofg2X/jMnCyZgL6y7eg==",
"dependencies": {
"@octokit/types": "^8.0.0",
"deprecation": "^2.0.0",
"once": "^1.4.0"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/@octokit/rest": {
"version": "19.0.5",
"resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.5.tgz",
"integrity": "sha512-+4qdrUFq2lk7Va+Qff3ofREQWGBeoTKNqlJO+FGjFP35ZahP+nBenhZiGdu8USSgmq4Ky3IJ/i4u0xbLqHaeow==",
"dependencies": {
"@octokit/core": "^4.1.0",
"@octokit/plugin-paginate-rest": "^5.0.0",
"@octokit/plugin-request-log": "^1.0.4",
"@octokit/plugin-rest-endpoint-methods": "^6.7.0"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/@octokit/types": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-8.0.0.tgz",
"integrity": "sha512-65/TPpOJP1i3K4lBJMnWqPUJ6zuOtzhtagDvydAWbEXpbFYA0oMKKyLb95NFZZP0lSh/4b6K+DQlzvYQJQQePg==",
"dependencies": {
"@octokit/openapi-types": "^14.0.0"
}
},
"node_modules/@posthog/plugin-scaffold": { "node_modules/@posthog/plugin-scaffold": {
"version": "1.3.4", "version": "1.3.4",
"resolved": "https://registry.npmjs.org/@posthog/plugin-scaffold/-/plugin-scaffold-1.3.4.tgz", "resolved": "https://registry.npmjs.org/@posthog/plugin-scaffold/-/plugin-scaffold-1.3.4.tgz",
@@ -2895,6 +3045,11 @@
"@types/node": "*" "@types/node": "*"
} }
}, },
"node_modules/@types/libsodium-wrappers": {
"version": "0.7.10",
"resolved": "https://registry.npmjs.org/@types/libsodium-wrappers/-/libsodium-wrappers-0.7.10.tgz",
"integrity": "sha512-BqI9B92u+cM3ccp8mpHf+HzJ8fBlRwdmyd6+fz3p99m3V6ifT5O3zmOMi612PGkpeFeG/G6loxUnzlDNhfjPSA=="
},
"node_modules/@types/mime": { "node_modules/@types/mime": {
"version": "3.0.1", "version": "3.0.1",
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz",
@@ -3485,6 +3640,11 @@
} }
] ]
}, },
"node_modules/before-after-hook": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz",
"integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ=="
},
"node_modules/bigint-conversion": { "node_modules/bigint-conversion": {
"version": "2.2.2", "version": "2.2.2",
"resolved": "https://registry.npmjs.org/bigint-conversion/-/bigint-conversion-2.2.2.tgz", "resolved": "https://registry.npmjs.org/bigint-conversion/-/bigint-conversion-2.2.2.tgz",
@@ -4054,6 +4214,11 @@
"node": ">= 0.8" "node": ">= 0.8"
} }
}, },
"node_modules/deprecation": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz",
"integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ=="
},
"node_modules/destroy": { "node_modules/destroy": {
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
@@ -5297,6 +5462,14 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/is-plain-object": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
"integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-stream": { "node_modules/is-stream": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
@@ -6122,6 +6295,19 @@
"node": ">= 0.8.0" "node": ">= 0.8.0"
} }
}, },
"node_modules/libsodium": {
"version": "0.7.10",
"resolved": "https://registry.npmjs.org/libsodium/-/libsodium-0.7.10.tgz",
"integrity": "sha512-eY+z7hDrDKxkAK+QKZVNv92A5KYkxfvIshtBJkmg5TSiCnYqZP3i9OO9whE79Pwgm4jGaoHgkM4ao/b9Cyu4zQ=="
},
"node_modules/libsodium-wrappers": {
"version": "0.7.10",
"resolved": "https://registry.npmjs.org/libsodium-wrappers/-/libsodium-wrappers-0.7.10.tgz",
"integrity": "sha512-pO3F1Q9NPLB/MWIhehim42b/Fwb30JNScCNh8TcQ/kIc+qGLQch8ag8wb0keK3EP5kbGakk1H8Wwo7v+36rNQg==",
"dependencies": {
"libsodium": "^0.7.0"
}
},
"node_modules/lines-and-columns": { "node_modules/lines-and-columns": {
"version": "1.2.4", "version": "1.2.4",
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
@@ -6508,6 +6694,44 @@
"resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="
}, },
"node_modules/node-fetch": {
"version": "2.6.7",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
"integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
"dependencies": {
"whatwg-url": "^5.0.0"
},
"engines": {
"node": "4.x || >=6.0.0"
},
"peerDependencies": {
"encoding": "^0.1.0"
},
"peerDependenciesMeta": {
"encoding": {
"optional": true
}
}
},
"node_modules/node-fetch/node_modules/tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
},
"node_modules/node-fetch/node_modules/webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
},
"node_modules/node-fetch/node_modules/whatwg-url": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
"dependencies": {
"tr46": "~0.0.3",
"webidl-conversions": "^3.0.0"
}
},
"node_modules/node-int64": { "node_modules/node-int64": {
"version": "0.4.0", "version": "0.4.0",
"resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
@@ -10622,6 +10846,11 @@
"integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==",
"dev": true "dev": true
}, },
"node_modules/universal-user-agent": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz",
"integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w=="
},
"node_modules/unpipe": { "node_modules/unpipe": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
@@ -13131,6 +13360,118 @@
"fastq": "^1.6.0" "fastq": "^1.6.0"
} }
}, },
"@octokit/auth-token": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-3.0.2.tgz",
"integrity": "sha512-pq7CwIMV1kmzkFTimdwjAINCXKTajZErLB4wMLYapR2nuB/Jpr66+05wOTZMSCBXP6n4DdDWT2W19Bm17vU69Q==",
"requires": {
"@octokit/types": "^8.0.0"
}
},
"@octokit/core": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.1.0.tgz",
"integrity": "sha512-Czz/59VefU+kKDy+ZfDwtOIYIkFjExOKf+HA92aiTZJ6EfWpFzYQWw0l54ji8bVmyhc+mGaLUbSUmXazG7z5OQ==",
"requires": {
"@octokit/auth-token": "^3.0.0",
"@octokit/graphql": "^5.0.0",
"@octokit/request": "^6.0.0",
"@octokit/request-error": "^3.0.0",
"@octokit/types": "^8.0.0",
"before-after-hook": "^2.2.0",
"universal-user-agent": "^6.0.0"
}
},
"@octokit/endpoint": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-7.0.3.tgz",
"integrity": "sha512-57gRlb28bwTsdNXq+O3JTQ7ERmBTuik9+LelgcLIVfYwf235VHbN9QNo4kXExtp/h8T423cR5iJThKtFYxC7Lw==",
"requires": {
"@octokit/types": "^8.0.0",
"is-plain-object": "^5.0.0",
"universal-user-agent": "^6.0.0"
}
},
"@octokit/graphql": {
"version": "5.0.4",
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-5.0.4.tgz",
"integrity": "sha512-amO1M5QUQgYQo09aStR/XO7KAl13xpigcy/kI8/N1PnZYSS69fgte+xA4+c2DISKqUZfsh0wwjc2FaCt99L41A==",
"requires": {
"@octokit/request": "^6.0.0",
"@octokit/types": "^8.0.0",
"universal-user-agent": "^6.0.0"
}
},
"@octokit/openapi-types": {
"version": "14.0.0",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-14.0.0.tgz",
"integrity": "sha512-HNWisMYlR8VCnNurDU6os2ikx0s0VyEjDYHNS/h4cgb8DeOxQ0n72HyinUtdDVxJhFy3FWLGl0DJhfEWk3P5Iw=="
},
"@octokit/plugin-paginate-rest": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-5.0.1.tgz",
"integrity": "sha512-7A+rEkS70pH36Z6JivSlR7Zqepz3KVucEFVDnSrgHXzG7WLAzYwcHZbKdfTXHwuTHbkT1vKvz7dHl1+HNf6Qyw==",
"requires": {
"@octokit/types": "^8.0.0"
}
},
"@octokit/plugin-request-log": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz",
"integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==",
"requires": {}
},
"@octokit/plugin-rest-endpoint-methods": {
"version": "6.7.0",
"resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-6.7.0.tgz",
"integrity": "sha512-orxQ0fAHA7IpYhG2flD2AygztPlGYNAdlzYz8yrD8NDgelPfOYoRPROfEyIe035PlxvbYrgkfUZIhSBKju/Cvw==",
"requires": {
"@octokit/types": "^8.0.0",
"deprecation": "^2.3.1"
}
},
"@octokit/request": {
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.2.tgz",
"integrity": "sha512-6VDqgj0HMc2FUX2awIs+sM6OwLgwHvAi4KCK3mT2H2IKRt6oH9d0fej5LluF5mck1lRR/rFWN0YIDSYXYSylbw==",
"requires": {
"@octokit/endpoint": "^7.0.0",
"@octokit/request-error": "^3.0.0",
"@octokit/types": "^8.0.0",
"is-plain-object": "^5.0.0",
"node-fetch": "^2.6.7",
"universal-user-agent": "^6.0.0"
}
},
"@octokit/request-error": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-3.0.2.tgz",
"integrity": "sha512-WMNOFYrSaX8zXWoJg9u/pKgWPo94JXilMLb2VManNOby9EZxrQaBe/QSC4a1TzpAlpxofg2X/jMnCyZgL6y7eg==",
"requires": {
"@octokit/types": "^8.0.0",
"deprecation": "^2.0.0",
"once": "^1.4.0"
}
},
"@octokit/rest": {
"version": "19.0.5",
"resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.5.tgz",
"integrity": "sha512-+4qdrUFq2lk7Va+Qff3ofREQWGBeoTKNqlJO+FGjFP35ZahP+nBenhZiGdu8USSgmq4Ky3IJ/i4u0xbLqHaeow==",
"requires": {
"@octokit/core": "^4.1.0",
"@octokit/plugin-paginate-rest": "^5.0.0",
"@octokit/plugin-request-log": "^1.0.4",
"@octokit/plugin-rest-endpoint-methods": "^6.7.0"
}
},
"@octokit/types": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-8.0.0.tgz",
"integrity": "sha512-65/TPpOJP1i3K4lBJMnWqPUJ6zuOtzhtagDvydAWbEXpbFYA0oMKKyLb95NFZZP0lSh/4b6K+DQlzvYQJQQePg==",
"requires": {
"@octokit/openapi-types": "^14.0.0"
}
},
"@posthog/plugin-scaffold": { "@posthog/plugin-scaffold": {
"version": "1.3.4", "version": "1.3.4",
"resolved": "https://registry.npmjs.org/@posthog/plugin-scaffold/-/plugin-scaffold-1.3.4.tgz", "resolved": "https://registry.npmjs.org/@posthog/plugin-scaffold/-/plugin-scaffold-1.3.4.tgz",
@@ -13416,6 +13757,11 @@
"@types/node": "*" "@types/node": "*"
} }
}, },
"@types/libsodium-wrappers": {
"version": "0.7.10",
"resolved": "https://registry.npmjs.org/@types/libsodium-wrappers/-/libsodium-wrappers-0.7.10.tgz",
"integrity": "sha512-BqI9B92u+cM3ccp8mpHf+HzJ8fBlRwdmyd6+fz3p99m3V6ifT5O3zmOMi612PGkpeFeG/G6loxUnzlDNhfjPSA=="
},
"@types/mime": { "@types/mime": {
"version": "3.0.1", "version": "3.0.1",
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz",
@@ -13833,6 +14179,11 @@
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
}, },
"before-after-hook": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz",
"integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ=="
},
"bigint-conversion": { "bigint-conversion": {
"version": "2.2.2", "version": "2.2.2",
"resolved": "https://registry.npmjs.org/bigint-conversion/-/bigint-conversion-2.2.2.tgz", "resolved": "https://registry.npmjs.org/bigint-conversion/-/bigint-conversion-2.2.2.tgz",
@@ -14253,6 +14604,11 @@
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
}, },
"deprecation": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz",
"integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ=="
},
"destroy": { "destroy": {
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
@@ -15163,6 +15519,11 @@
"integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
"dev": true "dev": true
}, },
"is-plain-object": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
"integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q=="
},
"is-stream": { "is-stream": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
@@ -15808,6 +16169,19 @@
"type-check": "~0.4.0" "type-check": "~0.4.0"
} }
}, },
"libsodium": {
"version": "0.7.10",
"resolved": "https://registry.npmjs.org/libsodium/-/libsodium-0.7.10.tgz",
"integrity": "sha512-eY+z7hDrDKxkAK+QKZVNv92A5KYkxfvIshtBJkmg5TSiCnYqZP3i9OO9whE79Pwgm4jGaoHgkM4ao/b9Cyu4zQ=="
},
"libsodium-wrappers": {
"version": "0.7.10",
"resolved": "https://registry.npmjs.org/libsodium-wrappers/-/libsodium-wrappers-0.7.10.tgz",
"integrity": "sha512-pO3F1Q9NPLB/MWIhehim42b/Fwb30JNScCNh8TcQ/kIc+qGLQch8ag8wb0keK3EP5kbGakk1H8Wwo7v+36rNQg==",
"requires": {
"libsodium": "^0.7.0"
}
},
"lines-and-columns": { "lines-and-columns": {
"version": "1.2.4", "version": "1.2.4",
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
@@ -16110,6 +16484,35 @@
"resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="
}, },
"node-fetch": {
"version": "2.6.7",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
"integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
"requires": {
"whatwg-url": "^5.0.0"
},
"dependencies": {
"tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
},
"webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
},
"whatwg-url": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
"requires": {
"tr46": "~0.0.3",
"webidl-conversions": "^3.0.0"
}
}
}
},
"node-int64": { "node-int64": {
"version": "0.4.0", "version": "0.4.0",
"resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
@@ -18917,6 +19320,11 @@
"integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==",
"dev": true "dev": true
}, },
"universal-user-agent": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz",
"integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w=="
},
"unpipe": { "unpipe": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+3
View File
@@ -1,9 +1,11 @@
{ {
"dependencies": { "dependencies": {
"@godaddy/terminus": "^4.11.2", "@godaddy/terminus": "^4.11.2",
"@octokit/rest": "^19.0.5",
"@sentry/node": "^7.14.0", "@sentry/node": "^7.14.0",
"@sentry/tracing": "^7.19.0", "@sentry/tracing": "^7.19.0",
"@types/crypto-js": "^4.1.1", "@types/crypto-js": "^4.1.1",
"@types/libsodium-wrappers": "^0.7.10",
"axios": "^1.1.3", "axios": "^1.1.3",
"bigint-conversion": "^2.2.2", "bigint-conversion": "^2.2.2",
"cookie-parser": "^1.4.6", "cookie-parser": "^1.4.6",
@@ -17,6 +19,7 @@
"helmet": "^5.1.1", "helmet": "^5.1.1",
"jsonwebtoken": "^8.5.1", "jsonwebtoken": "^8.5.1",
"jsrp": "^0.2.4", "jsrp": "^0.2.4",
"libsodium-wrappers": "^0.7.10",
"mongoose": "^6.7.2", "mongoose": "^6.7.2",
"nodemailer": "^6.8.0", "nodemailer": "^6.8.0",
"posthog-node": "^2.1.0", "posthog-node": "^2.1.0",
+5
View File
@@ -14,8 +14,11 @@ const CLIENT_SECRET_HEROKU = process.env.CLIENT_SECRET_HEROKU!;
const CLIENT_ID_HEROKU = process.env.CLIENT_ID_HEROKU!; const CLIENT_ID_HEROKU = process.env.CLIENT_ID_HEROKU!;
const CLIENT_ID_VERCEL = process.env.CLIENT_ID_VERCEL!; const CLIENT_ID_VERCEL = process.env.CLIENT_ID_VERCEL!;
const CLIENT_ID_NETLIFY = process.env.CLIENT_ID_NETLIFY!; const CLIENT_ID_NETLIFY = process.env.CLIENT_ID_NETLIFY!;
const CLIENT_ID_GITHUB =
process.env.CLIENT_ID_GITHUB! || 'e787fc24bcec43ecd5d5';
const CLIENT_SECRET_VERCEL = process.env.CLIENT_SECRET_VERCEL!; const CLIENT_SECRET_VERCEL = process.env.CLIENT_SECRET_VERCEL!;
const CLIENT_SECRET_NETLIFY = process.env.CLIENT_SECRET_NETLIFY!; const CLIENT_SECRET_NETLIFY = process.env.CLIENT_SECRET_NETLIFY!;
const CLIENT_SECRET_GITHUB = process.env.CLIENT_SECRET_GITHUB! || '407f32da788f63559abd662c6de08bb2911ca8ae';
const CLIENT_SLUG_VERCEL= process.env.CLIENT_SLUG_VERCEL!; const CLIENT_SLUG_VERCEL= process.env.CLIENT_SLUG_VERCEL!;
const POSTHOG_HOST = process.env.POSTHOG_HOST! || 'https://app.posthog.com'; const POSTHOG_HOST = process.env.POSTHOG_HOST! || 'https://app.posthog.com';
const POSTHOG_PROJECT_API_KEY = const POSTHOG_PROJECT_API_KEY =
@@ -54,9 +57,11 @@ export {
CLIENT_ID_HEROKU, CLIENT_ID_HEROKU,
CLIENT_ID_VERCEL, CLIENT_ID_VERCEL,
CLIENT_ID_NETLIFY, CLIENT_ID_NETLIFY,
CLIENT_ID_GITHUB,
CLIENT_SECRET_HEROKU, CLIENT_SECRET_HEROKU,
CLIENT_SECRET_VERCEL, CLIENT_SECRET_VERCEL,
CLIENT_SECRET_NETLIFY, CLIENT_SECRET_NETLIFY,
CLIENT_SECRET_GITHUB,
CLIENT_SLUG_VERCEL, CLIENT_SLUG_VERCEL,
POSTHOG_HOST, POSTHOG_HOST,
POSTHOG_PROJECT_API_KEY, POSTHOG_PROJECT_API_KEY,
+65 -29
View File
@@ -1,15 +1,16 @@
import axios from 'axios'; import axios from 'axios';
import * as Sentry from '@sentry/node'; import * as Sentry from '@sentry/node';
import { import { Octokit } from '@octokit/rest';
IIntegrationAuth import { IIntegrationAuth } from '../models';
} from '../models';
import { import {
INTEGRATION_HEROKU, INTEGRATION_HEROKU,
INTEGRATION_VERCEL, INTEGRATION_VERCEL,
INTEGRATION_NETLIFY, INTEGRATION_NETLIFY,
INTEGRATION_GITHUB,
INTEGRATION_HEROKU_API_URL, INTEGRATION_HEROKU_API_URL,
INTEGRATION_VERCEL_API_URL, INTEGRATION_VERCEL_API_URL,
INTEGRATION_NETLIFY_API_URL INTEGRATION_NETLIFY_API_URL,
INTEGRATION_GITHUB_API_URL
} from '../variables'; } from '../variables';
/** /**
@@ -27,7 +28,6 @@ const getApps = async ({
integrationAuth: IIntegrationAuth; integrationAuth: IIntegrationAuth;
accessToken: string; accessToken: string;
}) => { }) => {
interface App { interface App {
name: string; name: string;
siteId?: string; siteId?: string;
@@ -52,8 +52,13 @@ const getApps = async ({
accessToken accessToken
}); });
break; break;
case INTEGRATION_GITHUB:
apps = await getAppsGithub({
integrationAuth,
accessToken
});
break;
} }
} catch (err) { } catch (err) {
Sentry.setUser(null); Sentry.setUser(null);
Sentry.captureException(err); Sentry.captureException(err);
@@ -61,7 +66,7 @@ const getApps = async ({
} }
return apps; return apps;
} };
/** /**
* Return list of names of apps for Heroku integration * Return list of names of apps for Heroku integration
@@ -70,19 +75,17 @@ const getApps = async ({
* @returns {Object[]} apps - names of Heroku apps * @returns {Object[]} apps - names of Heroku apps
* @returns {String} apps.name - name of Heroku app * @returns {String} apps.name - name of Heroku app
*/ */
const getAppsHeroku = async ({ const getAppsHeroku = async ({ accessToken }: { accessToken: string }) => {
accessToken
}: {
accessToken: string;
}) => {
let apps; let apps;
try { try {
const res = (await axios.get(`${INTEGRATION_HEROKU_API_URL}/apps`, { const res = (
await axios.get(`${INTEGRATION_HEROKU_API_URL}/apps`, {
headers: { headers: {
Accept: 'application/vnd.heroku+json; version=3', Accept: 'application/vnd.heroku+json; version=3',
Authorization: `Bearer ${accessToken}` Authorization: `Bearer ${accessToken}`
} }
})).data; })
).data;
apps = res.map((a: any) => ({ apps = res.map((a: any) => ({
name: a.name name: a.name
@@ -94,7 +97,7 @@ const getAppsHeroku = async ({
} }
return apps; return apps;
} };
/** /**
* Return list of names of apps for Vercel integration * Return list of names of apps for Vercel integration
@@ -103,18 +106,16 @@ const getAppsHeroku = async ({
* @returns {Object[]} apps - names of Vercel apps * @returns {Object[]} apps - names of Vercel apps
* @returns {String} apps.name - name of Vercel app * @returns {String} apps.name - name of Vercel app
*/ */
const getAppsVercel = async ({ const getAppsVercel = async ({ accessToken }: { accessToken: string }) => {
accessToken
}: {
accessToken: string;
}) => {
let apps; let apps;
try { try {
const res = (await axios.get(`${INTEGRATION_VERCEL_API_URL}/v9/projects`, { const res = (
await axios.get(`${INTEGRATION_VERCEL_API_URL}/v9/projects`, {
headers: { headers: {
Authorization: `Bearer ${accessToken}` Authorization: `Bearer ${accessToken}`
} }
})).data; })
).data;
apps = res.projects.map((a: any) => ({ apps = res.projects.map((a: any) => ({
name: a.name name: a.name
@@ -126,7 +127,7 @@ const getAppsVercel = async ({
} }
return apps; return apps;
} };
/** /**
* Return list of names of sites for Netlify integration * Return list of names of sites for Netlify integration
@@ -144,17 +145,18 @@ const getAppsNetlify = async ({
}) => { }) => {
let apps; let apps;
try { try {
const res = (await axios.get(`${INTEGRATION_NETLIFY_API_URL}/api/v1/sites`, { const res = (
await axios.get(`${INTEGRATION_NETLIFY_API_URL}/api/v1/sites`, {
headers: { headers: {
Authorization: `Bearer ${accessToken}` Authorization: `Bearer ${accessToken}`
} }
})).data; })
).data;
apps = res.map((a: any) => ({ apps = res.map((a: any) => ({
name: a.name, name: a.name,
siteId: a.site_id siteId: a.site_id
})); }));
} catch (err) { } catch (err) {
Sentry.setUser(null); Sentry.setUser(null);
Sentry.captureException(err); Sentry.captureException(err);
@@ -162,8 +164,42 @@ const getAppsNetlify = async ({
} }
return apps; return apps;
};
/**
* Return list of names of repositories for Github integration
* @param {Object} obj
* @param {String} obj.accessToken - access token for Netlify API
* @returns {Object[]} apps - names of Netlify sites
* @returns {String} apps.name - name of Netlify site
*/
const getAppsGithub = async ({
integrationAuth,
accessToken
}: {
integrationAuth: IIntegrationAuth;
accessToken: string;
}) => {
let apps;
try {
const octokit = new Octokit({
auth: accessToken
});
const repos = await octokit.request(
'GET /user/repos{?visibility,affiliation,type,sort,direction,per_page,page,since,before}',
{}
);
apps = repos.map((a: any) => {
a.name;
});
} catch (err) {
Sentry.setUser(null);
Sentry.captureException(err);
throw new Error('Failed to get Github repos');
} }
export { return apps;
getApps };
}
export { getApps };
+121 -36
View File
@@ -4,19 +4,24 @@ import {
INTEGRATION_HEROKU, INTEGRATION_HEROKU,
INTEGRATION_VERCEL, INTEGRATION_VERCEL,
INTEGRATION_NETLIFY, INTEGRATION_NETLIFY,
INTEGRATION_GITHUB,
INTEGRATION_HEROKU_TOKEN_URL, INTEGRATION_HEROKU_TOKEN_URL,
INTEGRATION_VERCEL_TOKEN_URL, INTEGRATION_VERCEL_TOKEN_URL,
INTEGRATION_NETLIFY_TOKEN_URL, INTEGRATION_NETLIFY_TOKEN_URL,
INTEGRATION_GITHUB_TOKEN_URL,
ACTION_PUSH_TO_HEROKU ACTION_PUSH_TO_HEROKU
} from '../variables'; } from '../variables';
import { import {
SITE_URL, SITE_URL,
CLIENT_SECRET_HEROKU,
CLIENT_ID_VERCEL, CLIENT_ID_VERCEL,
CLIENT_ID_NETLIFY, CLIENT_ID_NETLIFY,
CLIENT_ID_GITHUB,
CLIENT_SECRET_VERCEL, CLIENT_SECRET_VERCEL,
CLIENT_SECRET_NETLIFY CLIENT_SECRET_NETLIFY,
CLIENT_SECRET_GITHUB
} from '../config'; } from '../config';
import { user } from '../routes';
interface ExchangeCodeHerokuResponse { interface ExchangeCodeHerokuResponse {
token_type: string; token_type: string;
@@ -43,6 +48,12 @@ interface ExchangeCodeNetlifyResponse {
created_at: number; created_at: number;
} }
interface ExchangeCodeGithubResponse {
access_token: string;
scope: string;
token_type: string;
}
/** /**
* Return [accessToken], [accessExpiresAt], and [refreshToken] for OAuth2 * Return [accessToken], [accessExpiresAt], and [refreshToken] for OAuth2
* code-token exchange for integration named [integration] * code-token exchange for integration named [integration]
@@ -81,6 +92,11 @@ const exchangeCode = async ({
code code
}); });
break; break;
case INTEGRATION_GITHUB:
obj = await exchangeCodeGithub({
code
});
break;
} }
} catch (err) { } catch (err) {
Sentry.setUser(null); Sentry.setUser(null);
@@ -89,7 +105,7 @@ const exchangeCode = async ({
} }
return obj; return obj;
} };
/** /**
* Return [accessToken], [accessExpiresAt], and [refreshToken] for Heroku * Return [accessToken], [accessExpiresAt], and [refreshToken] for Heroku
@@ -101,6 +117,36 @@ const exchangeCode = async ({
* @returns {String} obj2.refreshToken - refresh token for Heroku API * @returns {String} obj2.refreshToken - refresh token for Heroku API
* @returns {Date} obj2.accessExpiresAt - date of expiration for access token * @returns {Date} obj2.accessExpiresAt - date of expiration for access token
*/ */
<<<<<<< HEAD
const exchangeCodeHeroku = async ({ code }: { code: string }) => {
let res: ExchangeCodeHerokuResponse;
const accessExpiresAt = new Date();
try {
res = (
await axios.post(
INTEGRATION_HEROKU_TOKEN_URL,
new URLSearchParams({
grant_type: 'authorization_code',
code: code,
client_secret: OAUTH_CLIENT_SECRET_HEROKU
} as any)
)
).data;
accessExpiresAt.setSeconds(accessExpiresAt.getSeconds() + res.expires_in);
} catch (err) {
Sentry.setUser(null);
Sentry.captureException(err);
throw new Error('Failed OAuth2 code-token exchange with Heroku');
}
return {
accessToken: res.access_token,
refreshToken: res.refresh_token,
accessExpiresAt
};
};
=======
const exchangeCodeHeroku = async ({ const exchangeCodeHeroku = async ({
code code
}: { }: {
@@ -133,6 +179,7 @@ const exchangeCodeHeroku = async ({
accessExpiresAt accessExpiresAt
}); });
} }
>>>>>>> 5444382d5ae1fabf1107434a856b58b9f09c67f6
/** /**
* Return [accessToken], [accessExpiresAt], and [refreshToken] for Vercel * Return [accessToken], [accessExpiresAt], and [refreshToken] for Vercel
@@ -144,14 +191,11 @@ const exchangeCodeHeroku = async ({
* @returns {String} obj2.refreshToken - refresh token for Heroku API * @returns {String} obj2.refreshToken - refresh token for Heroku API
* @returns {Date} obj2.accessExpiresAt - date of expiration for access token * @returns {Date} obj2.accessExpiresAt - date of expiration for access token
*/ */
const exchangeCodeVercel = async ({ const exchangeCodeVercel = async ({ code }: { code: string }) => {
code
}: {
code: string;
}) => {
let res: ExchangeCodeVercelResponse; let res: ExchangeCodeVercelResponse;
try { try {
res = (await axios.post( res = (
await axios.post(
INTEGRATION_VERCEL_TOKEN_URL, INTEGRATION_VERCEL_TOKEN_URL,
new URLSearchParams({ new URLSearchParams({
code: code, code: code,
@@ -159,20 +203,21 @@ const exchangeCodeVercel = async ({
client_secret: CLIENT_SECRET_VERCEL, client_secret: CLIENT_SECRET_VERCEL,
redirect_uri: `${SITE_URL}/vercel` redirect_uri: `${SITE_URL}/vercel`
} as any) } as any)
)).data; )
).data;
} catch (err) { } catch (err) {
Sentry.setUser(null); Sentry.setUser(null);
Sentry.captureException(err); Sentry.captureException(err);
throw new Error('Failed OAuth2 code-token exchange with Vercel'); throw new Error('Failed OAuth2 code-token exchange with Vercel');
} }
return ({ return {
accessToken: res.access_token, accessToken: res.access_token,
refreshToken: null, refreshToken: null,
accessExpiresAt: null, accessExpiresAt: null,
teamId: res.team_id teamId: res.team_id
}); };
} };
/** /**
* Return [accessToken], [accessExpiresAt], and [refreshToken] for Vercel * Return [accessToken], [accessExpiresAt], and [refreshToken] for Vercel
@@ -184,15 +229,12 @@ const exchangeCodeVercel = async ({
* @returns {String} obj2.refreshToken - refresh token for Heroku API * @returns {String} obj2.refreshToken - refresh token for Heroku API
* @returns {Date} obj2.accessExpiresAt - date of expiration for access token * @returns {Date} obj2.accessExpiresAt - date of expiration for access token
*/ */
const exchangeCodeNetlify = async ({ const exchangeCodeNetlify = async ({ code }: { code: string }) => {
code
}: {
code: string;
}) => {
let res: ExchangeCodeNetlifyResponse; let res: ExchangeCodeNetlifyResponse;
let accountId; let accountId;
try { try {
res = (await axios.post( res = (
await axios.post(
INTEGRATION_NETLIFY_TOKEN_URL, INTEGRATION_NETLIFY_TOKEN_URL,
new URLSearchParams({ new URLSearchParams({
grant_type: 'authorization_code', grant_type: 'authorization_code',
@@ -201,41 +243,84 @@ const exchangeCodeNetlify = async ({
client_secret: CLIENT_SECRET_NETLIFY, client_secret: CLIENT_SECRET_NETLIFY,
redirect_uri: `${SITE_URL}/netlify` redirect_uri: `${SITE_URL}/netlify`
} as any) } as any)
)).data; )
).data;
const res2 = await axios.get( const res2 = await axios.get('https://api.netlify.com/api/v1/sites', {
'https://api.netlify.com/api/v1/sites',
{
headers: { headers: {
Authorization: `Bearer ${res.access_token}` Authorization: `Bearer ${res.access_token}`
} }
} });
);
const res3 = (await axios.get( const res3 = (
'https://api.netlify.com/api/v1/accounts', await axios.get('https://api.netlify.com/api/v1/accounts', {
{
headers: { headers: {
Authorization: `Bearer ${res.access_token}` Authorization: `Bearer ${res.access_token}`
} }
} })
)).data; ).data;
accountId = res3[0].id; accountId = res3[0].id;
} catch (err) { } catch (err) {
Sentry.setUser(null); Sentry.setUser(null);
Sentry.captureException(err); Sentry.captureException(err);
throw new Error('Failed OAuth2 code-token exchange with Netlify'); throw new Error('Failed OAuth2 code-token exchange with Netlify');
} }
return ({ return {
accessToken: res.access_token, accessToken: res.access_token,
refreshToken: res.refresh_token, refreshToken: res.refresh_token,
accountId accountId
}); };
};
/**
* Return [accessToken], [accessExpiresAt], and [refreshToken] for Github
* code-token exchange
* @param {Object} obj1
* @param {Object} obj1.code - code for code-token exchange
* @returns {Object} obj2
* @returns {String} obj2.accessToken - access token for Github API
* @returns {String} obj2.refreshToken - refresh token for Github API
* @returns {Date} obj2.accessExpiresAt - date of expiration for access token
*/
const exchangeCodeGithub = async ({ code }: { code: string }) => {
let res: ExchangeCodeGithubResponse;
let res2;
try {
res = (
await axios.get(INTEGRATION_GITHUB_TOKEN_URL, {
params: {
client_id: CLIENT_ID_GITHUB,
client_secret: CLIENT_SECRET_GITHUB,
code: code,
redirect_uri: `${SITE_URL}/github`
}
})
).data;
res2 = (
await axios.get(INTEGRATION_GITHUB_TOKEN_URL, {
params: {
Authorization: `Bearer ${res.access_token}`
}
})
).data;
} catch (err) {
Sentry.setUser(null);
Sentry.captureException(err);
throw new Error('Failed OAuth2 code-token exchange with Github');
} }
export { // TODO: Check actual response and fix next line
exchangeCode const accountId = res2.user;
}
return {
accessToken: res.access_token,
user: accountId,
refreshToken: null,
accessExpiresAt: null
};
};
export { exchangeCode };
+16 -5
View File
@@ -38,7 +38,7 @@ const exchangeRefresh = async ({
} }
return accessToken; return accessToken;
} };
/** /**
* Return new access token by exchanging refresh token [refreshToken] for the * Return new access token by exchanging refresh token [refreshToken] for the
@@ -52,6 +52,18 @@ const exchangeRefreshHeroku = async ({
}: { }: {
refreshToken: string; refreshToken: string;
}) => { }) => {
<<<<<<< HEAD
let accessToken;
try {
const res = await axios.post(
INTEGRATION_HEROKU_TOKEN_URL,
new URLSearchParams({
grant_type: 'refresh_token',
refresh_token: refreshToken,
client_secret: OAUTH_CLIENT_SECRET_HEROKU
} as any)
);
=======
let accessToken; let accessToken;
try { try {
const res = await axios.post( const res = await axios.post(
@@ -62,6 +74,7 @@ const exchangeRefreshHeroku = async ({
client_secret: CLIENT_SECRET_HEROKU client_secret: CLIENT_SECRET_HEROKU
} as any) } as any)
); );
>>>>>>> 5444382d5ae1fabf1107434a856b58b9f09c67f6
accessToken = res.data.access_token; accessToken = res.data.access_token;
} catch (err) { } catch (err) {
@@ -71,8 +84,6 @@ const exchangeRefreshHeroku = async ({
} }
return accessToken; return accessToken;
} };
export { export { exchangeRefresh };
exchangeRefresh
}
+9 -12
View File
@@ -1,22 +1,19 @@
import axios from 'axios'; import axios from 'axios';
import * as Sentry from '@sentry/node'; import * as Sentry from '@sentry/node';
import { import { IIntegrationAuth, IntegrationAuth, Integration } from '../models';
IIntegrationAuth,
IntegrationAuth,
Integration
} from '../models';
import { import {
INTEGRATION_HEROKU, INTEGRATION_HEROKU,
INTEGRATION_VERCEL, INTEGRATION_VERCEL,
INTEGRATION_NETLIFY INTEGRATION_NETLIFY,
INTEGRATION_GITHUB
} from '../variables'; } from '../variables';
const revokeAccess = async ({ const revokeAccess = async ({
integrationAuth, integrationAuth,
accessToken accessToken
}: { }: {
integrationAuth: IIntegrationAuth, integrationAuth: IIntegrationAuth;
accessToken: String accessToken: string;
}) => { }) => {
try { try {
// add any integration-specific revocation logic // add any integration-specific revocation logic
@@ -27,6 +24,8 @@ const revokeAccess = async ({
break; break;
case INTEGRATION_NETLIFY: case INTEGRATION_NETLIFY:
break; break;
case INTEGRATION_GITHUB:
break;
} }
const deletedIntegrationAuth = await IntegrationAuth.findOneAndDelete({ const deletedIntegrationAuth = await IntegrationAuth.findOneAndDelete({
@@ -43,8 +42,6 @@ const revokeAccess = async ({
Sentry.captureException(err); Sentry.captureException(err);
throw new Error('Failed to delete integration authorization'); throw new Error('Failed to delete integration authorization');
} }
} };
export { export { revokeAccess };
revokeAccess
}
+134 -16
View File
@@ -1,16 +1,19 @@
import axios from 'axios'; import axios from 'axios';
import * as Sentry from '@sentry/node'; import * as Sentry from '@sentry/node';
import { import { Octokit } from '@octokit/rest';
IIntegration, IIntegrationAuth import * as sodium from 'libsodium-wrappers';
} from '../models'; import { IIntegration, IIntegrationAuth } from '../models';
import { import {
INTEGRATION_HEROKU, INTEGRATION_HEROKU,
INTEGRATION_VERCEL, INTEGRATION_VERCEL,
INTEGRATION_NETLIFY, INTEGRATION_NETLIFY,
INTEGRATION_GITHUB,
INTEGRATION_HEROKU_API_URL, INTEGRATION_HEROKU_API_URL,
INTEGRATION_VERCEL_API_URL, INTEGRATION_VERCEL_API_URL,
INTEGRATION_NETLIFY_API_URL INTEGRATION_NETLIFY_API_URL,
INTEGRATION_GITHUB_API_URL
} from '../variables'; } from '../variables';
import { access, appendFile } from 'fs';
// TODO: need a helper function in the future to handle integration // TODO: need a helper function in the future to handle integration
// envar priorities (i.e. prioritize secrets within integration or those on Infisical) // envar priorities (i.e. prioritize secrets within integration or those on Infisical)
@@ -29,7 +32,7 @@ const syncSecrets = async ({
integration, integration,
integrationAuth, integrationAuth,
secrets, secrets,
accessToken, accessToken
}: { }: {
integration: IIntegration; integration: IIntegration;
integrationAuth: IIntegrationAuth; integrationAuth: IIntegrationAuth;
@@ -60,15 +63,20 @@ const syncSecrets = async ({
accessToken accessToken
}); });
break; break;
} case INTEGRATION_GITHUB:
await syncSecretsGitHub({
// TODO: set integration to inactive if it was not synced correctly (send alert?) integration,
integrationAuth,
secrets,
accessToken
});
break;
} catch (err) { } catch (err) {
Sentry.setUser(null); Sentry.setUser(null);
Sentry.captureException(err); Sentry.captureException(err);
throw new Error('Failed to sync secrets to integration'); throw new Error('Failed to sync secrets to integration');
} }
} };
/** /**
* Sync/push [secrets] to Heroku [app] * Sync/push [secrets] to Heroku [app]
@@ -81,12 +89,13 @@ const syncSecretsHeroku = async ({
secrets, secrets,
accessToken accessToken
}: { }: {
integration: IIntegration, integration: IIntegration;
secrets: any; secrets: any;
accessToken: string; accessToken: string;
}) => { }) => {
try { try {
const herokuSecrets = (await axios.get( const herokuSecrets = (
await axios.get(
`${INTEGRATION_HEROKU_API_URL}/apps/${integration.app}/config-vars`, `${INTEGRATION_HEROKU_API_URL}/apps/${integration.app}/config-vars`,
{ {
headers: { headers: {
@@ -94,9 +103,10 @@ const syncSecretsHeroku = async ({
Authorization: `Bearer ${accessToken}` Authorization: `Bearer ${accessToken}`
} }
} }
)).data; )
).data;
Object.keys(herokuSecrets).forEach(key => { Object.keys(herokuSecrets).forEach((key) => {
if (!(key in secrets)) { if (!(key in secrets)) {
secrets[key] = null; secrets[key] = null;
} }
@@ -117,7 +127,7 @@ const syncSecretsHeroku = async ({
Sentry.captureException(err); Sentry.captureException(err);
throw new Error('Failed to sync secrets to Heroku'); throw new Error('Failed to sync secrets to Heroku');
} }
} };
/** /**
* Sync/push [secrets] to Heroku [app] * Sync/push [secrets] to Heroku [app]
@@ -475,7 +485,115 @@ const syncSecretsNetlify = async ({
} }
} }
/**
* Sync/push [secrets] to GitHub site [app]
* @param {Object} obj
* @param {IIntegration} obj.integration - integration details
* @param {IIntegrationAuth} obj.integrationAuth - integration auth details
* @param {Object} obj.secrets - secrets to push to integration (object where keys are secret keys and values are secret values)
*/
const syncSecretsGitHub = async ({
integration,
integrationAuth,
secrets,
accessToken
}: {
integration: IIntegration;
integrationAuth: IIntegrationAuth;
secrets: any;
accessToken: string;
}) => {
try {
const deleteSecrets: Array<string> = [];
export { const octokit = new Octokit({
syncSecrets auth: accessToken
});
const loggedInUser = await octokit.request('GET /user', {});
// TODO: Check loggedInUser.login == repo owner
const repoPublicKey = await octokit.request(
'GET /repos/{owner}/{repo}/actions/secrets/public-key',
{
owner: loggedInUser.login,
repo: integration.app
} }
).key;
const userRepos = await octokit.request('GET /user/repos', {});
// Get local copy of decrypted secrets. We cannot decrypt them as we dont have access to GH private key
const encryptedSecrets = await octokit.request(
'GET /repos/{owner}/{repo}/actions/secrets',
{
owner: loggedInUser.name,
repo: integration.app
}
);
Object.keys(secrets).map((key) => {
if (!(key in encryptedSecrets)) {
deleteSecrets.push(key);
}
});
if (!Object.values(userRepos).includes(integration.app)) {
if (deleteSecrets.length == 0) {
throw new Error('Failed to sync secrets to Github');
}
}
// Sync/push all secrets
for (const i in secrets) {
let encryptedSecret;
sodium.ready.then(() => {
// Convert Secret & Base64 key to Uint8Array.
const binkey = sodium.from_base64(
repoPublicKey,
sodium.base64_variants.ORIGINAL
);
const binsec = sodium.from_string(secrets[i]);
//Encrypt the secret using LibSodium
const encBytes = sodium.crypto_box_seal(binsec, binkey);
// Convert encrypted Uint8Array to Base64
encryptedSecret = sodium.to_base64(
encBytes,
sodium.base64_variants.ORIGINAL
);
});
const res = await octokit.request(
'PUT /repos/{owner}/{repo}/actions/secrets/{secret_name}',
{
owner: loggedInUser.login,
repo: integration.app,
secret_name: Object.keys(secrets[i]),
encrypted_value: encryptedSecret,
key_id: '' //TODO: Not sure if we need this? https://docs.github.com/en/rest/actions/secrets?apiVersion=2022-11-28#create-or-update-a-repository-secret
}
);
}
// Delete secrets
if (deleteSecrets.length > 0) {
for (const i in deleteSecrets) {
const res = await octokit.request(
'DELETE /repos/{owner}/{repo}/actions/secrets/{secret_name}',
{
owner: loggedInUser.login,
repo: integration.app,
secret_name: secrets[i]
}
);
}
}
} catch (err) {
Sentry.setUser(null);
Sentry.captureException(err);
throw new Error('Failed to sync secrets to Github');
}
};
export { syncSecrets };
+13 -7
View File
@@ -6,7 +6,8 @@ import {
ENV_PROD, ENV_PROD,
INTEGRATION_HEROKU, INTEGRATION_HEROKU,
INTEGRATION_VERCEL, INTEGRATION_VERCEL,
INTEGRATION_NETLIFY INTEGRATION_NETLIFY,
INTEGRATION_GITHUB
} from '../variables'; } from '../variables';
export interface IIntegration { export interface IIntegration {
@@ -18,7 +19,7 @@ export interface IIntegration {
target: string; target: string;
context: string; context: string;
siteId: string; siteId: string;
integration: 'heroku' | 'vercel' | 'netlify'; integration: 'heroku' | 'vercel' | 'netlify' | 'github';
integrationAuth: Types.ObjectId; integrationAuth: Types.ObjectId;
} }
@@ -38,19 +39,23 @@ const integrationSchema = new Schema<IIntegration>(
type: Boolean, type: Boolean,
required: true required: true
}, },
app: { // name of app in provider app: {
// name of app in provider
type: String, type: String,
default: null default: null
}, },
target: { // vercel-specific target (environment) target: {
// vercel-specific target (environment)
type: String, type: String,
default: null default: null
}, },
context: { // netlify-specific context (deploy) context: {
// netlify-specific context (deploy)
type: String, type: String,
default: null default: null
}, },
siteId: { // netlify-specific site (app) id siteId: {
// netlify-specific site (app) id
type: String, type: String,
default: null default: null
}, },
@@ -59,7 +64,8 @@ const integrationSchema = new Schema<IIntegration>(
enum: [ enum: [
INTEGRATION_HEROKU, INTEGRATION_HEROKU,
INTEGRATION_VERCEL, INTEGRATION_VERCEL,
INTEGRATION_NETLIFY INTEGRATION_NETLIFY,
INTEGRATION_GITHUB
], ],
required: true required: true
}, },
+9 -5
View File
@@ -2,13 +2,14 @@ import { Schema, model, Types } from 'mongoose';
import { import {
INTEGRATION_HEROKU, INTEGRATION_HEROKU,
INTEGRATION_VERCEL, INTEGRATION_VERCEL,
INTEGRATION_NETLIFY INTEGRATION_NETLIFY,
INTEGRATION_GITHUB
} from '../variables'; } from '../variables';
export interface IIntegrationAuth { export interface IIntegrationAuth {
_id: Types.ObjectId; _id: Types.ObjectId;
workspace: Types.ObjectId; workspace: Types.ObjectId;
integration: 'heroku' | 'vercel' | 'netlify'; integration: 'heroku' | 'vercel' | 'netlify' | 'github';
teamId: string; teamId: string;
accountId: string; accountId: string;
refreshCiphertext?: string; refreshCiphertext?: string;
@@ -31,14 +32,17 @@ const integrationAuthSchema = new Schema<IIntegrationAuth>(
enum: [ enum: [
INTEGRATION_HEROKU, INTEGRATION_HEROKU,
INTEGRATION_VERCEL, INTEGRATION_VERCEL,
INTEGRATION_NETLIFY INTEGRATION_NETLIFY,
INTEGRATION_GITHUB
], ],
required: true required: true
}, },
teamId: { // vercel-specific integration param teamId: {
// vercel-specific integration param
type: String type: String
}, },
accountId: { // netlify-specific integration param accountId: {
// netlify-specific integration param
type: String type: String
}, },
refreshCiphertext: { refreshCiphertext: {
+10 -15
View File
@@ -9,14 +9,17 @@ import {
INTEGRATION_HEROKU, INTEGRATION_HEROKU,
INTEGRATION_VERCEL, INTEGRATION_VERCEL,
INTEGRATION_NETLIFY, INTEGRATION_NETLIFY,
INTEGRATION_GITHUB,
INTEGRATION_SET, INTEGRATION_SET,
INTEGRATION_OAUTH2, INTEGRATION_OAUTH2,
INTEGRATION_HEROKU_TOKEN_URL, INTEGRATION_HEROKU_TOKEN_URL,
INTEGRATION_VERCEL_TOKEN_URL, INTEGRATION_VERCEL_TOKEN_URL,
INTEGRATION_NETLIFY_TOKEN_URL, INTEGRATION_NETLIFY_TOKEN_URL,
INTEGRATION_GITHUB_TOKEN_URL,
INTEGRATION_HEROKU_API_URL, INTEGRATION_HEROKU_API_URL,
INTEGRATION_VERCEL_API_URL, INTEGRATION_VERCEL_API_URL,
INTEGRATION_NETLIFY_API_URL, INTEGRATION_NETLIFY_API_URL,
INTEGRATION_GITHUB_API_URL,
INTEGRATION_OPTIONS INTEGRATION_OPTIONS
} from './integration'; } from './integration';
import { import {
@@ -28,21 +31,10 @@ import {
COMPLETED, COMPLETED,
GRANTED GRANTED
} from './organization'; } from './organization';
import { import { SECRET_SHARED, SECRET_PERSONAL } from './secret';
SECRET_SHARED, import { PLAN_STARTER, PLAN_PRO } from './stripe';
SECRET_PERSONAL import { EVENT_PUSH_SECRETS, EVENT_PULL_SECRETS } from './event';
} from './secret'; import { ACTION_PUSH_TO_HEROKU } from './action';
import {
PLAN_STARTER,
PLAN_PRO
} from './stripe';
import {
EVENT_PUSH_SECRETS,
EVENT_PULL_SECRETS
} from './event';
import {
ACTION_PUSH_TO_HEROKU
} from './action';
export { export {
OWNER, OWNER,
@@ -64,14 +56,17 @@ export {
INTEGRATION_HEROKU, INTEGRATION_HEROKU,
INTEGRATION_VERCEL, INTEGRATION_VERCEL,
INTEGRATION_NETLIFY, INTEGRATION_NETLIFY,
INTEGRATION_GITHUB,
INTEGRATION_SET, INTEGRATION_SET,
INTEGRATION_OAUTH2, INTEGRATION_OAUTH2,
INTEGRATION_HEROKU_TOKEN_URL, INTEGRATION_HEROKU_TOKEN_URL,
INTEGRATION_VERCEL_TOKEN_URL, INTEGRATION_VERCEL_TOKEN_URL,
INTEGRATION_NETLIFY_TOKEN_URL, INTEGRATION_NETLIFY_TOKEN_URL,
INTEGRATION_GITHUB_TOKEN_URL,
INTEGRATION_HEROKU_API_URL, INTEGRATION_HEROKU_API_URL,
INTEGRATION_VERCEL_API_URL, INTEGRATION_VERCEL_API_URL,
INTEGRATION_NETLIFY_API_URL, INTEGRATION_NETLIFY_API_URL,
INTEGRATION_GITHUB_API_URL,
EVENT_PUSH_SECRETS, EVENT_PUSH_SECRETS,
EVENT_PULL_SECRETS, EVENT_PULL_SECRETS,
ACTION_PUSH_TO_HEROKU, ACTION_PUSH_TO_HEROKU,
+12 -3
View File
@@ -8,10 +8,12 @@ import {
const INTEGRATION_HEROKU = 'heroku'; const INTEGRATION_HEROKU = 'heroku';
const INTEGRATION_VERCEL = 'vercel'; const INTEGRATION_VERCEL = 'vercel';
const INTEGRATION_NETLIFY = 'netlify'; const INTEGRATION_NETLIFY = 'netlify';
const INTEGRATION_GITHUB = 'github';
const INTEGRATION_SET = new Set([ const INTEGRATION_SET = new Set([
INTEGRATION_HEROKU, INTEGRATION_HEROKU,
INTEGRATION_VERCEL, INTEGRATION_VERCEL,
INTEGRATION_NETLIFY INTEGRATION_NETLIFY,
INTEGRATION_GITHUB
]); ]);
// integration types // integration types
@@ -19,13 +21,17 @@ const INTEGRATION_OAUTH2 = 'oauth2';
// integration oauth endpoints // integration oauth endpoints
const INTEGRATION_HEROKU_TOKEN_URL = 'https://id.heroku.com/oauth/token'; const INTEGRATION_HEROKU_TOKEN_URL = 'https://id.heroku.com/oauth/token';
const INTEGRATION_VERCEL_TOKEN_URL = 'https://api.vercel.com/v2/oauth/access_token'; const INTEGRATION_VERCEL_TOKEN_URL =
'https://api.vercel.com/v2/oauth/access_token';
const INTEGRATION_NETLIFY_TOKEN_URL = 'https://api.netlify.com/oauth/token'; const INTEGRATION_NETLIFY_TOKEN_URL = 'https://api.netlify.com/oauth/token';
const INTEGRATION_GITHUB_TOKEN_URL =
'https://github.com/login/oauth/access_token';
// integration apps endpoints // integration apps endpoints
const INTEGRATION_HEROKU_API_URL = 'https://api.heroku.com'; const INTEGRATION_HEROKU_API_URL = 'https://api.heroku.com';
const INTEGRATION_VERCEL_API_URL = 'https://api.vercel.com'; const INTEGRATION_VERCEL_API_URL = 'https://api.vercel.com';
const INTEGRATION_NETLIFY_API_URL = 'https://api.netlify.com'; const INTEGRATION_NETLIFY_API_URL = 'https://api.netlify.com';
const INTEGRATION_GITHUB_API_URL = ' https://api.github.com/';
const INTEGRATION_OPTIONS = [ const INTEGRATION_OPTIONS = [
{ {
@@ -107,13 +113,16 @@ export {
INTEGRATION_HEROKU, INTEGRATION_HEROKU,
INTEGRATION_VERCEL, INTEGRATION_VERCEL,
INTEGRATION_NETLIFY, INTEGRATION_NETLIFY,
INTEGRATION_GITHUB,
INTEGRATION_SET, INTEGRATION_SET,
INTEGRATION_OAUTH2, INTEGRATION_OAUTH2,
INTEGRATION_HEROKU_TOKEN_URL, INTEGRATION_HEROKU_TOKEN_URL,
INTEGRATION_VERCEL_TOKEN_URL, INTEGRATION_VERCEL_TOKEN_URL,
INTEGRATION_NETLIFY_TOKEN_URL, INTEGRATION_NETLIFY_TOKEN_URL,
INTEGRATION_GITHUB_TOKEN_URL,
INTEGRATION_HEROKU_API_URL, INTEGRATION_HEROKU_API_URL,
INTEGRATION_VERCEL_API_URL, INTEGRATION_VERCEL_API_URL,
INTEGRATION_NETLIFY_API_URL, INTEGRATION_NETLIFY_API_URL,
INTEGRATION_GITHUB_API_URL,
INTEGRATION_OPTIONS INTEGRATION_OPTIONS
} };
+37
View File
@@ -0,0 +1,37 @@
import React, { useEffect } from "react";
import Head from "next/head";
import { useRouter } from "next/router";
const queryString = require("query-string");
import AuthorizeIntegration from "./api/integrations/authorizeIntegration";
export default function Github() {
const router = useRouter();
const parsedUrl = queryString.parse(router.asPath.split("?")[1]);
const code = parsedUrl.code;
const state = parsedUrl.state;
/**
* Here we forward to the default workspace if a user opens this url
*/
// eslint-disable-next-line react-hooks/exhaustive-deps
useEffect(async () => {
try {
if (state === localStorage.getItem('latestCSRFToken')) {
localStorage.removeItem('latestCSRFToken');
await AuthorizeIntegration({
workspaceId: localStorage.getItem('projectData.id'),
code,
integration: "github",
});
router.push("/integrations/" + localStorage.getItem("projectData.id"));
}
} catch (error) {
console.error('Github integration error: ', error);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
return <div></div>;
}
Github.requireAuth = true;
+8
View File
@@ -137,6 +137,14 @@ export default function Integrations() {
window.location = `https://vercel.com/integrations/${integrationOption.clientSlug}/new?state=${state}`; window.location = `https://vercel.com/integrations/${integrationOption.clientSlug}/new?state=${state}`;
break; break;
case 'Netlify': case 'Netlify':
window.location = `https://app.netlify.com/authorize?client_id=${integrationOption.clientId}&response_type=code&redirect_uri=${integrationOption.redirectURL}&state=${state}`;
break;
case 'Github':
window.location = `https://github.com.com/login/oauth/authorize?client_id=${integrationOption.clientId}&response_type=code&redirect_uri=${integrationOption.redirectURL}&state=${state}`;
break;
case 'Fly.io':
console.log('fly.io');
setIntegrationAccessTokenDialogOpen(true);
window.location = `https://app.netlify.com/authorize?client_id=${integrationOption.clientId}&response_type=code&state=${state}&redirect_uri=${window.location.origin}/netlify`; window.location = `https://app.netlify.com/authorize?client_id=${integrationOption.clientId}&response_type=code&state=${state}&redirect_uri=${window.location.origin}/netlify`;
break; break;
// case 'Fly.io': // case 'Fly.io':