user bin listing
This commit is contained in:
+83
-16
@@ -14,19 +14,17 @@ const db = new Pool({
|
||||
const app = express();
|
||||
const port = 80;
|
||||
|
||||
db.query("CREATE TABLE IF NOT EXISTS bin (id VARCHAR PRIMARY KEY);"
|
||||
db.query("CREATE TABLE IF NOT EXISTS bin (id VARCHAR PRIMARY KEY, name VARCHAR);"
|
||||
+ "CREATE TABLE IF NOT EXISTS note (id VARCHAR PRIMARY KEY, text TEXT, modified TIMESTAMPTZ);"
|
||||
+ "CREATE TABLE IF NOT EXISTS bin_note (bin_id VARCHAR REFERENCES bin (id), note_id VARCHAR REFERENCES note (id), PRIMARY KEY (bin_id, note_id));"
|
||||
+ "CREATE TABLE IF NOT EXISTS user_ (id VARCHAR PRIMARY KEY, username TEXT, password TEXT);" // table 'user' is already taken
|
||||
+ "CREATE TABLE IF NOT EXISTS bin_user (bin_id VARCHAR REFERENCES bin (id), user_id VARCHAR REFERENCES user_ (id), PRIMARY KEY (bin_id, user_id));"
|
||||
+ "CREATE TABLE IF NOT EXISTS session (id VARCHAR PRIMARY KEY, user_id VARCHAR REFERENCES user_ (id));"
|
||||
);
|
||||
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
router.get('/', (req, res)=>{
|
||||
res.send('Feh')
|
||||
});
|
||||
|
||||
const load_notes_stmt =
|
||||
"SELECT n.id, n.text, n.modified FROM bin_note AS bn"
|
||||
+" JOIN note AS n"
|
||||
@@ -37,7 +35,26 @@ router.post('/load-notes', (req, res)=>{
|
||||
const bin_id = req.body.bin_id;
|
||||
db.query(load_notes_stmt, [bin_id])
|
||||
.then(result => {
|
||||
res.json({status: 'ok', bin:{id:bin_id}, notes:result.rows})
|
||||
res.json({success:true, notes:result.rows})
|
||||
});
|
||||
});
|
||||
|
||||
const load_bin_stmt =
|
||||
"SELECT b.id, b.name FROM bin AS b"
|
||||
+" WHERE b.id = $1";
|
||||
// {bin_id}
|
||||
router.post('/load-bin', (req, res)=>{
|
||||
const bin_id = req.body.bin_id;
|
||||
db.query(load_bin_stmt, [bin_id])
|
||||
.then(result => {
|
||||
const bin = result.rows[0];
|
||||
// if a bin with given id was found:
|
||||
if(result.rows.length>0){
|
||||
res.json({success:true, bin:{id:bin.id, name:bin.name}});
|
||||
}
|
||||
else{
|
||||
res.json({success:false, bin:{id:bin_id, name:bin_id}});
|
||||
}
|
||||
});
|
||||
// {status: 'ok', bin:{id:bin.id}, notes: bin.notes}
|
||||
});
|
||||
@@ -61,24 +78,33 @@ const upsert_note_stmt =
|
||||
+" ON CONFLICT (id)"
|
||||
+" DO UPDATE SET text = EXCLUDED.text, modified = EXCLUDED.modified";
|
||||
const upsert_bin_stmt =
|
||||
"INSERT INTO bin (id) VALUES ($1)"
|
||||
"INSERT INTO bin (id, name) VALUES ($1, $1)"
|
||||
+" ON CONFLICT (id)"
|
||||
+" DO NOTHING";
|
||||
const upsert_bin_note_stmt =
|
||||
"INSERT INTO bin_note (bin_id, note_id) VALUES ($1, $2)"
|
||||
+" ON CONFLICT (bin_id, note_id)"
|
||||
+" DO NOTHING";
|
||||
|
||||
const upsert_bin_user_stmt =
|
||||
"INSERT INTO bin_user (bin_id, user_id)"
|
||||
+" (SELECT $1, s.user_id FROM session AS s WHERE s.id = $2)"
|
||||
+" ON CONFLICT (bin_id, user_id)"
|
||||
+" DO NOTHING";
|
||||
// {bin_id, note_id, text}
|
||||
router.post('/save', (req, res)=>{
|
||||
const {bin_id, note_id, text} = req.body;
|
||||
const {bin_id, note_id, text, session_id} = req.body;
|
||||
db.connect().then(async (client)=>{
|
||||
// TODO: make the following into a transaction:
|
||||
await client.query(upsert_note_stmt, [note_id, text]);
|
||||
await client.query(upsert_bin_stmt, [bin_id]);
|
||||
await client.query(upsert_bin_note_stmt, [bin_id, note_id]);
|
||||
// if the user is signed-in, ensure the bin and user are associated:
|
||||
if(session_id !== ''){
|
||||
await client.query(upsert_bin_user_stmt, [bin_id, session_id]);
|
||||
}
|
||||
// don't forget to release back into the Pool:
|
||||
client.release();
|
||||
res.json({status: 'ok'});
|
||||
res.json({success:true});
|
||||
});
|
||||
// {status: 'ok'}
|
||||
});
|
||||
@@ -88,17 +114,32 @@ const login_check_stmt =
|
||||
+" WHERE u.username = $1";
|
||||
const register_stmt =
|
||||
"INSERT INTO user_ (id, username, password) VALUES ($1, $2, $3)";
|
||||
const session_create_stmt =
|
||||
"INSERT INTO session (id, user_id) VALUES ($1, $2)";
|
||||
const user_bin_list_stmt =
|
||||
"SELECT b.id, b.name FROM bin_user AS bu"
|
||||
+" INNER JOIN bin AS b"
|
||||
+" ON bu.bin_id = b.id"
|
||||
+" WHERE bu.user_id = $1";
|
||||
router.post('/login', (req, res)=>{
|
||||
const {username, password_from_client} = req.body;
|
||||
const {username, password} = req.body;
|
||||
const password_from_client=password;
|
||||
db.query(login_check_stmt, [username])
|
||||
.then(result=>{
|
||||
// if there is such a username:
|
||||
if(result.rows.length > 0){
|
||||
const row = result.rows[0];
|
||||
const id=row.id, password_from_db=row.password;
|
||||
const user_id=row.id, password_from_db=row.password;
|
||||
// if the passwords match:
|
||||
// TODO: replace `===` with a constant-time comparison function to prevent timing attacks; or better, store passwords as salted hashes and use `===` on that:
|
||||
if(password_from_client === password_from_db){
|
||||
res.json({success:true, user:{id, username}, session_id:nanoid()});
|
||||
const session_id = nanoid();
|
||||
db.query(session_create_stmt, [session_id, user_id]);
|
||||
db.query(user_bin_list_stmt, [user_id])
|
||||
.then(result=>{
|
||||
const bins = result.rows;
|
||||
res.json({success:true, user:{id:user_id, username}, session_id, bins});
|
||||
});
|
||||
}
|
||||
else{
|
||||
res.json({success: false});
|
||||
@@ -106,15 +147,41 @@ router.post('/login', (req, res)=>{
|
||||
}
|
||||
// if no such user exists:
|
||||
else{
|
||||
const id = nanoid();
|
||||
db.query(register_stmt, [id, username, password_from_client])
|
||||
const user_id = nanoid();
|
||||
const session_id = nanoid();
|
||||
db.query(register_stmt, [user_id, username, password_from_client])
|
||||
.then(r=>{
|
||||
res.json({success: true, user:{id, username}, session_id:nanoid()});
|
||||
db.query(session_create_stmt, [session_id, user_id]);
|
||||
res.json({success: true, user:{id:user_id, username}, session_id, bins:[]});
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const delete_session_stmt =
|
||||
"DELETE FROM session WHERE id = $1";
|
||||
router.post('/logout', (req, res)=>{
|
||||
db.query(delete_session_stmt, [req.body.session_id]);
|
||||
res.json({success:true});
|
||||
});
|
||||
|
||||
const rename_bin_stmt =
|
||||
"INSERT INTO bin (id, name) VALUES ($1, $2)"
|
||||
+" ON CONFLICT (id)"
|
||||
+" DO UPDATE SET name = EXCLUDED.name;";
|
||||
router.post('/bin-rename', (req,res)=>{
|
||||
const {bin_id, name, session_id} = req.body;
|
||||
db.query(rename_bin_stmt, [bin_id, name])
|
||||
.then(x=>{
|
||||
// ensure user and bin are associated if necessary:
|
||||
if(session_id !== ''){
|
||||
// `upsert_bin_user_stmt` is defined above:
|
||||
db.query(upsert_bin_user_stmt, [bin_id, session_id]);
|
||||
}
|
||||
res.json({success:true});
|
||||
});
|
||||
});
|
||||
|
||||
app.use('/', express.json(), router);
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user