diff --git a/.env.local.sample b/.env.local.sample new file mode 100644 index 0000000..5798cf9 Binary files /dev/null and b/.env.local.sample differ diff --git a/README.md b/README.md index 40edde0..8a257dd 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,28 @@ A directory of Nation3 Citizens and their profiles +## Environment Variables + +### GitHub + +How to create a new OAuth App: + +1. Go to https://github.com/organizations/nation3/settings/applications + +1. Click "New OAuth App" + + - Application name: Nation3 Citizen Directory + + - Homepage URL: https://citizens.nation3.org + + - Authorization callback URL: https://citizens.nation3.org + +Add the environment variables to `.env.local`: + +``` +cp .env.local.sample .env.local +``` + ## Build ``` diff --git a/package-lock.json b/package-lock.json index cd9b2e4..4821699 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,6 +17,7 @@ "eslint": "8.38.0", "eslint-config-next": "13.3.0", "next": "13.3.0", + "next-connect": "^1.0.0", "papaparse": "^5.4.1", "passport": "^0.6.0", "passport-github2": "^0.1.12", @@ -31,7 +32,8 @@ "wagmi": "^1.4.2" }, "devDependencies": { - "@types/papaparse": "^5.3.7" + "@types/papaparse": "^5.3.7", + "dotenv": "^16.3.1" } }, "node_modules/@adraffy/ens-normalize": { @@ -897,6 +899,11 @@ "@tanstack/react-query": "^4.35.3" } }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==" + }, "node_modules/@types/connect": { "version": "3.4.36", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.36.tgz", @@ -2550,6 +2557,18 @@ "node": ">=6.0.0" } }, + "node_modules/dotenv": { + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", + "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/motdotla/dotenv?sponsor=1" + } + }, "node_modules/duplexify": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", @@ -4578,6 +4597,18 @@ } } }, + "node_modules/next-connect": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-connect/-/next-connect-1.0.0.tgz", + "integrity": "sha512-FeLURm9MdvzY1SDUGE74tk66mukSqL6MAzxajW7Gqh6DZKBZLrXmXnGWtHJZXkfvoi+V/DUe9Hhtfkl4+nTlYA==", + "dependencies": { + "@tsconfig/node16": "^1.0.3", + "regexparam": "^2.0.1" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/next/node_modules/postcss": { "version": "8.4.14", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz", @@ -5380,6 +5411,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/regexparam": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexparam/-/regexparam-2.0.1.tgz", + "integrity": "sha512-zRgSaYemnNYxUv+/5SeoHI0eJIgTL/A2pUtXUPLHQxUldagouJ9p+K6IbIZ/JiQuCEv2E2B1O11SjVQy3aMCkw==", + "engines": { + "node": ">=8" + } + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -7406,6 +7445,11 @@ "@tanstack/query-persist-client-core": "4.35.3" } }, + "@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==" + }, "@types/connect": { "version": "3.4.36", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.36.tgz", @@ -8698,6 +8742,12 @@ "esutils": "^2.0.2" } }, + "dotenv": { + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", + "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", + "dev": true + }, "duplexify": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", @@ -10183,6 +10233,15 @@ } } }, + "next-connect": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-connect/-/next-connect-1.0.0.tgz", + "integrity": "sha512-FeLURm9MdvzY1SDUGE74tk66mukSqL6MAzxajW7Gqh6DZKBZLrXmXnGWtHJZXkfvoi+V/DUe9Hhtfkl4+nTlYA==", + "requires": { + "@tsconfig/node16": "^1.0.3", + "regexparam": "^2.0.1" + } + }, "node-addon-api": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", @@ -10709,6 +10768,11 @@ "functions-have-names": "^1.2.2" } }, + "regexparam": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexparam/-/regexparam-2.0.1.tgz", + "integrity": "sha512-zRgSaYemnNYxUv+/5SeoHI0eJIgTL/A2pUtXUPLHQxUldagouJ9p+K6IbIZ/JiQuCEv2E2B1O11SjVQy3aMCkw==" + }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", diff --git a/package.json b/package.json index 71f5132..48abec7 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "eslint": "8.38.0", "eslint-config-next": "13.3.0", "next": "13.3.0", + "next-connect": "^1.0.0", "papaparse": "^5.4.1", "passport": "^0.6.0", "passport-github2": "^0.1.12", @@ -32,6 +33,7 @@ "wagmi": "^1.4.2" }, "devDependencies": { - "@types/papaparse": "^5.3.7" + "@types/papaparse": "^5.3.7", + "dotenv": "^16.3.1" } } diff --git a/src/components/ProfileDetailsGitHub.tsx b/src/components/ProfileDetailsGitHub.tsx index 86fcb34..3301d99 100644 --- a/src/components/ProfileDetailsGitHub.tsx +++ b/src/components/ProfileDetailsGitHub.tsx @@ -4,14 +4,14 @@ import GitHub from "../../abis/GitHub.json" import { useIsMounted } from "../../hooks/useIsMounted" import Link from "next/link" -export default function ProfileDetailsGitHub({ address }: any) { +export default function ProfileDetailsGitHub({ citizen }: any) { console.info('ProfileDetailsGitHub') const { data, isError, isLoading } = useContractRead({ address: '0xb989c0c17a3bce679d7586d9e55b6eab11c18687', abi: GitHub.abi, functionName: 'usernames', - args: [ address ] + args: [ citizen.ownerAddress ] }) console.info('data:', data) console.info('isError:', isError) @@ -29,7 +29,8 @@ export default function ProfileDetailsGitHub({ address }: any) { return ( <> Not linked - + {/* */} + Link my GitHub account 🔗 diff --git a/src/pages/[passportId].tsx b/src/pages/[passportId].tsx index d299210..a247520 100644 --- a/src/pages/[passportId].tsx +++ b/src/pages/[passportId].tsx @@ -88,7 +88,7 @@ export default function ProfilePage({ citizen, nationCred, veNation, dework, sou
  • GitHub account
    - +
  • Discord account
    diff --git a/src/pages/[passportId]/auth/github.tsx b/src/pages/[passportId]/auth/github.tsx new file mode 100644 index 0000000..a0864e7 --- /dev/null +++ b/src/pages/[passportId]/auth/github.tsx @@ -0,0 +1,42 @@ +import Menu from "@/components/Menu" +import { NextPage } from "next" +import Link from "next/link" +import { useRouter } from "next/router" + +const GitHubPage: NextPage = () => { + console.info('GitHubPage') + + const router = useRouter() + + return ( + <> +
    + + +
    +
    +
    +

    + Citizen #{router.query.passportId} +

    +
    +
    + +
    +

    Link My GitHub Account

    +
    + + Authenticate With GitHub + +
    +
    +
    +
    + + ) +} + +export default GitHubPage diff --git a/src/pages/api/[passportId]/auth/github.ts b/src/pages/api/[passportId]/auth/github.ts new file mode 100644 index 0000000..1d9dbfb --- /dev/null +++ b/src/pages/api/[passportId]/auth/github.ts @@ -0,0 +1,44 @@ +import nc, { createEdgeRouter } from "next-connect" +import { NextFetchEvent, NextRequest } from "next/server" +const passport = require('passport') +const GitHubStrategy = require('passport-github2').Strategy + +const callbackBaseUrl = process.env['GITHUB_CALLBACK_BASE_URL'] +console.info('callbackBaseUrl:', callbackBaseUrl) + +const callbackUrl = `${callbackBaseUrl}/api/233/auth/github-callback` // TODO: get [passportId] +console.info('callbackUrl:', callbackUrl) + +const router = createEdgeRouter() +router.use(async (request, event, next) => { + // logging request example + console.log(`${request.method} ${request.url}`); + return next(); +}); + +// Configure strategy +passport.use(new GitHubStrategy( + { + clientID: process.env['GITHUB_CLIENT_ID'], + clientSecret: process.env['GITHUB_CLIENT_SECRET'], + callbackURL: callbackUrl + }, + function(accessToken: any, refreshToken: any, profile: any, done: any) { + console.info('accessToken:', accessToken) + console.info('refreshToken:', refreshToken) + console.info('profile:', profile) + console.info('profile.username:', profile.username) + console.info('done:', done) + return done(null, profile) + } +)) + +// // Redirect to GitHub authentication +// const handler = nc() +// .get( +// passport.authenticate('github', { +// scope: ['user:email'] +// }) +// ) + +// export default handler