Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Milestone 2 and 3 #2

Open
wants to merge 17 commits into
base: github_auth
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,8 @@ yarn && yarn run deploy:composite

After that, please open http://localhost:3002/ and login with metamask. A button will appear. Click that button to authenticate yourself with your Github account. Once you authenticate, relevant public information will be collected from Github about you and will be stored in composedb. The information that was gathered will appear in the page. Next time you visit http://localhost:3002/ and authenticate with metamask, the page will fetch previously collected information about the user and display on the page.

Click on `Add your fiverr ratings` to go to the fiverr page. Then click `Get a token` button to get a token. Then, copy the token and paste the token in your fiverr description. Your fiverr ratings and related information will be collected from the page.

# Additional info about [credential-oracle](/credential-oracle/) example and its scripts

It is important to have the composedb cli installed in the local machine to play with or change the schema. To install ceramic cli globally, run:
Expand Down
60 changes: 48 additions & 12 deletions composedb/app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,36 +5,72 @@
from db import cursor

PORT = os.getenv('GET_QUERY_PORT', 8000)
DB_TABLE = os.getenv('DB_TABLE')
DB_TABLE_GITHUB = os.getenv('DB_TABLE_GITHUB')
DB_TABLE_FIVERR = os.getenv('DB_TABLE_FIVERR')

app = FastAPI()


def fetch_from_db(query):
result = None
try:
result = cursor.execute(query).fetchone()
except Exception as e:
raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Something went wrong.")

if not result:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND,
detail=f"Not found.")

return result


def format_doc(doc):
id, json_string = doc
record = json.loads(json_string)
record["id"] = id
return record


@app.get("/get-github-profile/{user_acount}")
def get_github_profile(user_acount):
# TECHDEBT
# This API will be removed once composedb implements the feature to query with fields
# https://forum.ceramic.network/t/queries-by-fields/260/6
query = f'''
SELECT stream_id, stream_content
FROM {DB_TABLE}
FROM {DB_TABLE_GITHUB}
WHERE json_extract(stream_content, '$.user_account')="{user_acount}"
'''
result = None
try:
result = cursor.execute(query).fetchone()
result = fetch_from_db(query)
except Exception as e:
raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Something went wrong.")
raise e
record = format_doc(result)

if not result:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND,
detail=f"Github profile with user_account: {user_acount} not found")
id, json_string = result
github_profile = json.loads(json_string)
github_profile["id"] = id
return record


@app.get("/fiverr-profile/{user_acount}")
def get_fiverr_profile(user_acount):
# TECHDEBT
# This API will be removed once composedb implements the feature to query with fields
# https://forum.ceramic.network/t/queries-by-fields/260/6
query = f'''
SELECT stream_id, stream_content
FROM {DB_TABLE_FIVERR}
WHERE json_extract(stream_content, '$.user_account')="{user_acount}"
'''
result = None
try:
result = fetch_from_db(query)
except Exception as e:
raise e
record = format_doc(result)

return github_profile
return record


if __name__ == "__main__":
Expand Down
22 changes: 21 additions & 1 deletion credential-input/src/App.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import GithubAuth from "./containers/GithubAuth";
import React, { useState, useEffect } from "react";
import getWeb3 from "./web3";
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import FiverrPage from "./containers/FiverrPage";
import "./App.css";
import FiverrAuth from "./containers/FiverrAuth";

function App() {
const web3 = getWeb3();
Expand Down Expand Up @@ -33,13 +36,30 @@ function App() {
setIsMetamaskConnected(true);
};

const router = createBrowserRouter([
{
path: "/",
element: (
<>
<GithubAuth userAccount={mainAccount} />
<br />
<FiverrAuth />
</>
),
},
{
path: "/cred/fiverr",
element: <FiverrPage userAccount={mainAccount} />,
},
]);

return (
<div className="App">
<header className="App-header">
{!isMetamaskInstalled && <p> Metamask not installed</p>}
{!isMetamaskConnected && <button onClick={connect}> Connect </button>}
{isMetamaskConnected && mainAccount && (
<GithubAuth userAccount={mainAccount} />
<RouterProvider router={router} />
)}
</header>
</div>
Expand Down
14 changes: 14 additions & 0 deletions credential-input/src/containers/FiverrAuth/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import "./style.css";
import { Link } from "react-router-dom";

const FiverrAuth = () => {
return (
<div className="button__margin">
<Link to="/cred/fiverr" className="btn">
<span className="text__wrapper">Add your fiverr ratings</span>
</Link>
</div>
);
};

export default FiverrAuth;
3 changes: 3 additions & 0 deletions credential-input/src/containers/FiverrAuth/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.button__margin {
margin-top: 16px;
}
141 changes: 141 additions & 0 deletions credential-input/src/containers/FiverrPage/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
import { useCallback, useState, useEffect } from "react";
import "./style.css";
import axios from "axios";

const BACKEND_BASE_URL = process.env.REACT_APP_BACKEND_BASE_URL;

const FiverrPage = (props) => {
const { userAccount } = props;

const [isRequestingMagicLink, setIsRequestingMagicLink] = useState(false);
const [isRequestingFiverrLink, setIsRequestingFiverrLink] = useState(false);
const [magicLink, setMagicLink] = useState();
const [textCopy, setTextCopy] = useState("Copy");
const [result, setResult] = useState();

const copyLink = useCallback(() => {
// Get the text field
var copyText = document.getElementById("magicLink");

// Select the text field
copyText.select();
copyText.setSelectionRange(0, 99999); // For mobile devices

// Copy the text inside the text field
navigator.clipboard.writeText(copyText.value);

// Alert the copied text
setTextCopy("Copied");

setTimeout(() => {
setTextCopy("Copy");
}, 3000);
}, []);

useEffect(() => {
const getFiverrProfileURL = `${BACKEND_BASE_URL}/fiverr-profile/${userAccount}`;
setIsRequestingFiverrLink(true);
axios
.get(getFiverrProfileURL)
.then((res) => {
setResult(res.data.message);
})
.catch((err) => {
console.error(err.message);
})
.finally(() => {
setIsRequestingFiverrLink(false);
});
}, []);

const getLink = useCallback(() => {
if (userAccount) {
setIsRequestingMagicLink(true);
const getFiverrMagicLink = `${BACKEND_BASE_URL}/get-fiverr-magic-link?userAccount=${userAccount}`;
axios
.get(getFiverrMagicLink)
.then((res) => {
setMagicLink(res.data.magicToken);
})
.catch((err) => {
console.error(err.message);
})
.finally(() => {
setIsRequestingMagicLink(false);
});
}
}, [userAccount]);

const sendLink = useCallback((e) => {
e.preventDefault();
setIsRequestingFiverrLink(true);
var url = document.getElementById("fiverrLink").value;
const sendFiverrLink = `${BACKEND_BASE_URL}/fiverr-profile/`;
axios
.post(sendFiverrLink, { url, userAccount })
.then((res) => {
setResult(res.data.message);
})
.catch((err) => {
console.error(err.message);
})
.finally(() => {
setIsRequestingFiverrLink(false);
});
}, []);

return (
<div>
{userAccount && (
<>
<p className="text">Get a token</p>
<button
disabled={isRequestingMagicLink}
onClick={getLink}
className="btn"
>
<span className="text__wrapper">
{isRequestingMagicLink ? "Loading..." : "Get a token"}
</span>
</button>

<p className="text">
Copy and paste this token into your Fiverr profile's description
section. Keep it until we are done getting your fiverr ratings and
info. Token valid for 15 minutes only.
</p>
<div>
<input id="magicLink" value={magicLink} readOnly />
<button
className="btn-right"
onClick={copyLink}
disabled={!magicLink}
>
{textCopy}
</button>
</div>
<p className="text">
Then share your public profile url in the below box and confirm
</p>
<form onSubmit={sendLink}>
<input
pattern="^https://www.fiverr.com/(.*)$"
placeholder="https://www.fiverr.com/chirag8838"
id="fiverrLink"
/>
<button
className="btn-right"
type="submit"
disabled={isRequestingFiverrLink}
>
{isRequestingFiverrLink ? "Loading..." : "Confirm"}
</button>
</form>
</>
)}
{result && <pre>{JSON.stringify(result, undefined, 2)}</pre>}
</div>
);
};

export default FiverrPage;
39 changes: 39 additions & 0 deletions credential-input/src/containers/FiverrPage/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
.btn {
height: 40px;
min-width: 100px;
border-radius: 10px;
background-color: #fafcff;
font-size: 14px;
letter-spacing: .1px;
cursor: pointer;
display: flex;
align-items: center;
padding: 10px 16px;
border: 1px solid black;
text-decoration: none;
color: inherit;
}

.btn-right {
margin-left: 12px;
}

.btn:hover {
background-color: rgb(221, 221, 221);
}

.text__wrapper {
margin-right: 10px;
display: block;
}

.text {
font-size: 14px;
}

pre {
font-size: 12px;
padding: 12px;
background: antiquewhite;
border-radius: 5px;
}
3 changes: 0 additions & 3 deletions credential-input/src/index.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
import React from "react";
import ReactDOM from "react-dom/client";
import { BrowserRouter } from "react-router-dom";

import App from "./App";
import "./index.css";

ReactDOM.createRoot(document.getElementById("root")).render(
<React.StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>
);
2 changes: 1 addition & 1 deletion credential-oracle/.env
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
GITHUB_USER_MODEL_STREAM_ID=kjzl6hvfrbw6c5no55wlukc496fea0iujswirvarqnode65vmh5fjb2w926sqph
CERAMIC_NODE_URL=http://localhost:7007
COMPOSITE_FILE_NAME=github_user_composite.json
COMPOSITE_FILE_NAME=merged_composite.json
DID_PRIVATE_KEY=59e83c249b8947d1524a3f5f66326c78759c86d75573027e7bef571c3fddfb90
5 changes: 5 additions & 0 deletions credential-oracle/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
FROM node:16.13-alpine3.14

RUN apk add --no-cache chromium

ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD true
ENV PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium-browser

WORKDIR /usr/src/app

COPY package.json yarn.lock ./
Expand Down
Loading