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

#34 install and setup synpress #37

Merged
merged 3 commits into from
May 3, 2024
Merged
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,058 changes: 1,899 additions & 159 deletions backend/package-lock.json

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,12 @@
"bcrypt": "^5.1.1",
"client-oauth2": "^4.3.3",
"cors": "^2.8.5",
"dotenv": "^16.3.1",
"dotenv": "^16.4.5",
"ethers": "^6.7.1",
"express": "^4.18.2",
"express-validator": "^7.0.1",
"jsonwebtoken": "^9.0.2",
"layer8-interceptor-wasm": "^1.0.2",
"layer8-middleware-wasm": "^1.0.2",
"nodemon": "^3.0.2",
"pg": "^8.11.3",
Expand All @@ -41,4 +42,4 @@
"engines": {
"node": ">=18"
}
}
}
106 changes: 106 additions & 0 deletions backend/src/controllers/cryptoTransactionController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
require('dotenv').config()
const { validationResult } = require('express-validator')
const jwt = require('jsonwebtoken')
const pool = require('../db')
const sanitizeUserInput = require('../utils/sanitizeUserInput')
const validateInput = require('../middlewares/validateInput')
const { secret } = require('../middlewares/jwtConfig')

// Route to add a new poem to the 'cryptoTransactions' table
const create = async (req, res) => {
const client = await pool.connect();
try {
await client.query('BEGIN'); // Start a transaction

const { poem_id, tx_hash } = req.body; // Assuming poem_id and tx_hash are provided in the request body
console.log("the req========= ", req.body);
const authorizationHeader = req.headers.authorization;
if (!authorizationHeader || !authorizationHeader.startsWith('Bearer ')) {
return res.status(401).json({ error: 'Bearer token not provided' });
}

const token = authorizationHeader.split(' ')[1];
const decoded = jwt.verify(token, secret);
const userId = decoded.id;

// First, insert the new transaction
const insertQuery = `
INSERT INTO cryptoTransactions (poem_id, user_id, tx_hash, created_at)
VALUES ($1, $2, $3, NOW())
RETURNING id;
`;
const result = await client.query(insertQuery, [poem_id, userId, tx_hash]);
const { id } = result.rows[0];

// Update the is_paid status in the poems table
const updatePoemQuery = `
UPDATE poems
SET is_paid = TRUE
WHERE id = $1;
`;
await client.query(updatePoemQuery, [poem_id]);

await client.query('COMMIT');
res.status(201).json({ id, message: 'CryptoTransaction added and poem marked as paid successfully' });
} catch (error) {
await client.query('ROLLBACK');
console.error('Error during creating transaction and updating poem:', error);
res.status(500).json({ error: 'Error during creating transaction and updating poem' });
} finally {
client.release();
}
};


// Route to get all cryptoTransactions from the 'cryptoTransactions' table with likes and dislikes
const read = async (req, res) => {
const client = await pool.connect();
try {
const queryParams = [];
const whereConditions = [];

if (req.query.tx_hash) {
queryParams.push(`%${req.query.tx_hash}%`);
whereConditions.push(`cryptoTransactions.tx_hash ILIKE $${queryParams.length}`);
}

if (req.query.poem_id) {
queryParams.push(parseInt(req.query.poem_id)); // Convert to integer to ensure the input is a valid number
whereConditions.push(`cryptoTransactions.poem_id = $${queryParams.length}`);
}

let selectQuery = `
SELECT
cryptotransactions.id, cryptotransactions.tx_hash, cryptotransactions.created_at, cryptotransactions.poem_id, cryptotransactions.user_id,
users.name AS user_name,
poems.title AS poem_title
FROM cryptotransactions
JOIN users ON users.id = cryptotransactions.user_id
JOIN poems ON poems.id = cryptotransactions.poem_id
`;

if (whereConditions.length > 0) {
selectQuery += ' WHERE ' + whereConditions.join(' AND ');
}

const result = await client.query(selectQuery, queryParams);
const cryptoTransactions = result.rows;

client.release();
res.json(cryptoTransactions);
} catch (error) {
console.error('Error getting cryptoTransactions:', error);
res.status(500).json({ error: 'Error getting cryptoTransactions' });
}
};



module.exports = {
create: [
// Use the validateInput middleware to validate the request body
validateInput(['tx_hash', 'poem_id']),
create
],
read,
}
8 changes: 6 additions & 2 deletions backend/src/controllers/poemController.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ const create = async (req, res) => {
const read = async (req, res) => {
try {
const client = await pool.connect()

console.log('the readd is calleddd================= ')
// Build the WHERE conditions and the query parameters based on the query string
const queryParams = []
const whereConditions = []
Expand All @@ -85,8 +85,10 @@ const read = async (req, res) => {
poems.content,
poems.created_at,
poems.title,
poems.is_paid,
users.id AS user_id,
users.name AS user_name,
users.eth_address AS user_eth_address,
(
SELECT ARRAY_AGG(user_id)
FROM likes
Expand All @@ -110,8 +112,10 @@ const read = async (req, res) => {
id: row.id,
author: {
id: row.user_id,
name: row.user_name
name: row.user_name,
eth_address: row.user_eth_address
},
is_paid: row.is_paid,
content: row.content,
created_at: row.created_at,
dislikes: row.dislikes || [],
Expand Down
2 changes: 1 addition & 1 deletion backend/src/controllers/swagger.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const spec = {
},
servers: [
{ url: 'https://api-wevegotpoems.up.railway.app/v1', description: 'Production server' },
{ url: 'http://localhost:51787/v1', description: 'Local server' }
{ url: 'http://localhost:8000/v1', description: 'Local server' }
],
paths: {
'/login': {
Expand Down
52 changes: 52 additions & 0 deletions backend/src/fixtures.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
[
{
"user_id": 1,
"title": "The Road Not Taken",
"content": "Two roads diverged in a yellow wood,\nAnd sorry I could not travel both\nAnd be one traveler, long I stood\nAnd looked down one as far as I could\nTo where it bent in the undergrowth;\n\nThen took the other, as just as fair,\nAnd having perhaps the better claim,\nBecause it was grassy and wanted wear;\nThough as for that the passing there\nHad worn them really about the same,\n\nAnd both that morning equally lay\nIn leaves no step had trodden black.\nOh, I kept the first for another day!\nYet knowing how way leads on to way,\nI doubted if I should ever come back.\n\nI shall be telling this with a sigh\nSomewhere ages and ages hence:\nTwo roads diverged in a wood, and I—\nI took the one less traveled by,\nAnd that has made all the difference."
},
{
"user_id": 1,
"title": "If",
"content": "If you can keep your head when all about you\nAre losing theirs and blaming it on you,\nIf you can trust yourself when all men doubt you,\nBut make allowance for their doubting too;\nIf you can wait and not be tired by waiting,\nOr being lied about, don’t deal in lies,\nOr being hated, don’t give way to hating,\nAnd yet don’t look too good, nor talk too wise:\n\nIf you can dream—and not make dreams your master;\nIf you can think—and not make thoughts your aim;\nIf you can meet with Triumph and Disaster\nAnd treat those two impostors just the same;\nIf you can bear to hear the truth you’ve spoken\nTwisted by knaves to make a trap for fools,\nOr watch the things you gave your life to, broken,\nAnd stoop and build ’em up with worn-out tools:\n\nIf you can make one heap of all your winnings\nAnd risk it on one turn of pitch-and-toss,\nAnd lose, and start again at your beginnings\nAnd never breathe a word about your loss;\nIf you can force your heart and nerve and sinew\nTo serve your turn long after they are gone,\nAnd so hold on when there is nothing in you\nExcept the Will which says to them: ‘Hold on!’\n\nIf you can talk with crowds and keep your virtue,\nOr walk with Kings—nor lose the common touch,\nIf neither foes nor loving friends can hurt you,\nIf all men count with you, but none too much;\nIf you can fill the unforgiving minute\nWith sixty seconds’ worth of distance run,\nYours is the Earth and everything that’s in it,\nAnd—which is more—you’ll be a Man, my son!"
},
{
"user_id": 3,
"title": "Stopping by Woods on a Snowy Evening",
"content": "Whose woods these are I think I know.\nHis house is in the village though;\nHe will not see me stopping here\nTo watch his woods fill up with snow.\n\nMy little horse must think it queer\nTo stop without a farmhouse near\nBetween the woods and frozen lake\nThe darkest evening of the year.\n\nHe gives his harness bells a shake\nTo ask if there is some mistake.\nThe only other sound’s the sweep\nOf easy wind and downy flake.\n\nThe woods are lovely, dark and deep,\nBut I have promises to keep,\nAnd miles to go before I sleep,\nAnd miles to go before I sleep."
},
{
"user_id": 8,
"title": "The Love Song of J. Alfred Prufrock",
"content": "Let us go then, you and I,\nWhen the evening is spread out against the sky\nLike a patient etherized upon a table;\nLet us go, through certain half-deserted streets,\nThe muttering retreats\nOf restless nights in one-night cheap hotels\nAnd sawdust restaurants with oyster-shells:\nStreets that follow like a tedious argument\nOf insidious intent\nTo lead you to an overwhelming question...\nOh, do not ask, “What is it?”\nLet us go and make our visit."
},
{
"user_id": 2,
"title": "Invictus",
"content": "Out of the night that covers me,\nBlack as the pit from pole to pole,\nI thank whatever gods may be\nFor my unconquerable soul.\n\nIn the fell clutch of circumstance\nI have not winced nor cried aloud.\nUnder the bludgeonings of chance\nMy head is bloody, but unbowed.\n\nBeyond this place of wrath and tears\nLooms but the Horror of the shade,\nAnd yet the menace of the years\nFinds and shall find me unafraid.\n\nIt matters not how strait the gate,\nHow charged with punishments the scroll,\nI am the master of my fate,\nI am the captain of my soul."
},
{
"user_id": 6,
"title": "The Raven",
"content": "Once upon a midnight dreary, while I pondered, weak and weary,\nOver many a quaint and curious volume of forgotten lore—\nWhile I nodded, nearly napping, suddenly there came a tapping,\nAs of some one gently rapping, rapping at my chamber door.\n“’Tis some visitor,” I muttered, “tapping at my chamber door—\n Only this and nothing more.”"
},
{
"user_id": 5,
"title": "Ozymandias",
"content": "I met a traveller from an antique land\nWho said: Two vast and trunkless legs of stone\nStand in the desart. Near them, on the sand,\nHalf sunk, a shattered visage lies, whose frown,\nAnd wrinkled lip, and sneer of cold command,\nTell that its sculptor well those passions read\nWhich yet survive, stamped on these lifeless things,\nThe hand that mocked them and the heart that fed:\nAnd on the pedestal these words appear:\nMy name is Ozymandias, king of kings:\nLook on my works, ye Mighty, and despair!\nNothing beside remains. Round the decay\nOf that colossal wreck, boundless and bare\nThe lone and level sands stretch far away."
},
{
"user_id": 8,
"title": "Fire and Ice",
"content": "Some say the world will end in fire,\nSome say in ice.\nFrom what I’ve tasted of desire\nI hold with those who favor fire.\nBut if it had to perish twice,\nI think I know enough of hate\nTo say that for destruction ice\nIs also great\nAnd would suffice."
},
{
"user_id": 1,
"title": "Annabel Lee",
"content": "It was many and many a year ago,\nIn a kingdom by the sea,\nThat a maiden there lived whom you may know\nBy the name of Annabel Lee;\nAnd this maiden she lived with no other thought\nThan to love and be loved by me."
},
{
"user_id": 2,
"title": "The Charge of the Light Brigade",
"content": "Half a league, half a league,\nHalf a league onward,\nAll in the valley of Death\nRode the six hundred.\n“Forward, the Light Brigade!\nCharge for the guns!” he said.\nInto the valley of Death\nRode the six hundred."
}
]
9 changes: 9 additions & 0 deletions backend/src/routes/cryptoTransactionsRoutes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const express = require('express')
const router = express.Router()
const cryptoTransactionController = require('../controllers/cryptoTransactionController')

router.post('/ctransactions', cryptoTransactionController.create)
router.get('/ctransactions', cryptoTransactionController.read)


module.exports = router
95 changes: 84 additions & 11 deletions backend/src/script.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
// Script to create the tables
const { Client } = require('pg')
require('dotenv').config()
const fs = require('fs')
const { Client } = require('pg')

// Load fixtures data from the JSON file
const fixturesData = require('./fixtures.json')

// Function to generate a fake wallet address
function generateWalletAddress() {
// You can implement your logic to generate a random wallet address here
// For simplicity, let's generate a random string
const randomString = Math.random().toString(36).substring(7)
return `0x${randomString}`
}

console.log(process.env.EXTERNAL_DB_URL)
const client = new Client({
connectionString: process.env.EXTERNAL_DB_URL,
ssl: false
connectionString: process.env.EXTERNAL_DB_URL
})

//const client = new Client(dbConfig);
// Query SQL to create the 'users' table
const createUserTableQuery = `
CREATE TABLE IF NOT EXISTS users (
Expand All @@ -27,7 +37,8 @@ const createPoemsTableQuery = `
user_id INT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
content TEXT NOT NULL,
created_at TIMESTAMP NOT NULL,
title VARCHAR(255) NOT NULL
title VARCHAR(255) NOT NULL,
is_paid BOOLEAN NOT NULL DEFAULT FALSE
);
`

Expand All @@ -41,19 +52,81 @@ const createReactionsTableQuery = `
);
`

// Connect to the database and execute the query
const createCryptoTransactionsTableQuery = `
CREATE TABLE IF NOT EXISTS cryptoTransactions (
id SERIAL PRIMARY KEY,
user_id INT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
poem_id INT NOT NULL REFERENCES poems(id) ON DELETE CASCADE,
tx_hash VARCHAR(255) NOT NULL,
created_at TIMESTAMP NOT NULL
);
`

// Function to insert data into the 'users' table
async function insertUsers() {
const userData = fixturesData.map((poem, index) => ({
name: `User${index + 1}`,
email: `user${index + 1}@example.com`,
eth_address: generateWalletAddress(),
password: '',
created_at: new Date().toISOString()
}))

const insertQuery = `
INSERT INTO users (name, email, eth_address, password, created_at)
VALUES ${userData.map((_, i) => `($${i * 5 + 1}, $${i * 5 + 2}, $${i * 5 + 3}, $${i * 5 + 4}, $${i * 5 + 5})`).join(', ')}
RETURNING *
`

try {
const res = await client.query(
insertQuery,
userData.flatMap((user) => [user.name, user.email, user.eth_address, user.password, user.created_at])
)
console.log(`${res.rowCount} users inserted successfully`)
} catch (err) {
console.error('Error inserting users:', err)
}
}

// Function to insert data into the 'poems' table
async function insertPoems() {
const poemData = fixturesData.map((poem) => ({
user_id: poem.user_id, // Assuming user_id is provided in the fixtures data
content: poem.content,
created_at: new Date().toISOString(),
title: poem.title
}))

const insertQuery = `
INSERT INTO poems (user_id, content, created_at, title)
VALUES ${poemData.map((_, i) => `($${i * 4 + 1}, $${i * 4 + 2}, $${i * 4 + 3}, $${i * 4 + 4})`).join(', ')}
`

try {
await client.query(
insertQuery,
poemData.flatMap((poem) => [poem.user_id, poem.content, poem.created_at, poem.title])
)
console.log(`${poemData.length} poems inserted successfully`)
} catch (err) {
console.error('Error inserting poems:', err)
}
}

// Connect to the database and execute the queries
client
.connect()
.then(async () => {
await client.query(createUserTableQuery)
await client.query(createPoemsTableQuery)
await client.query(createReactionsTableQuery)
})
.then(() => {
console.log('Table created successfully')
await client.query(createCryptoTransactionsTableQuery)
await insertUsers()
await insertPoems()
})
.catch((err) => {
console.error('Error creating table:', err)
console.error('Error connecting to the database:', err)
})
.finally(() => {
// Close the database connection
Expand Down
9 changes: 5 additions & 4 deletions backend/src/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,21 +36,22 @@ app.get('/healthcheck', (req, res) => {
})

const Layer8 = require('./dist/loadWASM.js')
app.use(Layer8)
const configRoutes = require('./routes/configRoutes')
app.use('/config', configRoutes) // Uncomment if you want to use the config routes
//app.use(Layer8)

app.use(cors())
app.use(express.json())

const authRoutes = require('./routes/authRoutes')
const configRoutes = require('./routes/configRoutes')
const likeRoutes = require('./routes/likeRoutes')
const poemRoutes = require('./routes/poemRoutes')
const cryptoTransactionRoute = require('./routes/cryptoTransactionsRoutes')
const userRoutes = require('./routes/userRoutes')
const swaggerRoute = require('./routes/swaggerRoute')

app.use('/', swaggerRoute)
app.use('/v1', authRoutes, likeRoutes, poemRoutes, userRoutes)
app.use('/config', configRoutes) // Uncomment if you want to use the config routes
app.use('/v1', authRoutes, likeRoutes, poemRoutes, userRoutes, cryptoTransactionRoute)

app.listen(port, () => {
console.log(`Server is listening on http://localhost:${port}`)
Expand Down
9 changes: 9 additions & 0 deletions frontend/.editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
root = true

[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
Loading
Loading