garagescript / databases Goto Github PK
View Code? Open in Web Editor NEWPlay with databases without account
Home Page: https://learndatabases.dev/
Play with databases without account
Home Page: https://learndatabases.dev/
High level overview - make sure to plan out your function!
Make sure to follow rest conventions
Signup:
POST /api/users
Delete Users:
DELET /api/users/:id
As a developer, I can safely rely on the User Module to create and edit user accounts.
createUser
-> This creates a user account in the databasegetUser
-> returns information about the userdeleteUser
-> deletes user account and all relevant informationisConfirmed
-> return true / false if user has confirmed their accounthasDBPassword
-> return true/false if user has database password.As a developer, I want to be able to run a sendEmail
function with an email and a type. The email function should take care of sending the email.
Email should also generate email Template Strings.
const {generateTemplate, sendEmail } = require('./email')
sendEmail( '[email protected]', 'subject string', generateTemplate('confirmation', data) )
helper functions.
const signup = (userObj) => {
signup
should take in email
, username
, password
.
username
contains invalid characters (must be alpha numeric)email
is invalidusername
/ password
is too short / longCode like this one unknowingly exposes user password to the internet: https://github.com/garageScript/databases/blob/master/src/routes/userRoutes.js#L89
Maybe add comment to users.js
file saying... Make sure to always delete password before returning user object
POST /api/notification
https://github.com/garageScript/databases/wiki/Routes-and-APIs#post-apinotification
POST /api/passwordReset
Sound send 2 things in the body
User should be able to create a database.
Call PG Module with username and dbPassword
logger.error
should accept error object, objects, and/or string.
All the other logger functions should allow for objects, strings, array, or other data types.
If it is error
, you can call the .toString()
method.
https://stackoverflow.com/questions/30469261/checking-for-typeof-error-in-js
JSON.stringify( [1,2,3], null, 2)
/
and just renders welcome/
to match snapshot.POST /api/sessions
DELETE /api/sessions
Create .env.example
and with sample information and comments about what each env variable is used for.
.env.example
to .env
and what accounts users have to create / setup to get the variables needed..gitignore
to ignore .env
files so nobody will accidentally commit that file./databases
-postgres text
-create postgres button
Navigate to one of these endpoints after signing in.
https://c0d3.com/teacher/1
https://c0d3.com/teacher/2
https://c0d3.com/teacher/3
https://c0d3.com/teacher/4
https://c0d3.com/teacher/5
https://c0d3.com/teacher/24
https://c0d3.com/teacher/25
https://c0d3.com/teacher/27
https://c0d3.com/teacher/28
https://c0d3.com/teacher/29
Example: DataDog
Databases
src/server.js
startServer
function that takes in a port number and runs app.listen
stopServer
function that stops the server. Lookup express documentation.
integration/server.js
with a beforeAll
function that runs startServer
End point: /databases/postgres
-port number
-database name
etc.
This PR partially made the pg module unusable, need to fix: https://github.com/garageScript/databases/pull/42/files
the other issue that PG module face is the IF NOT
query does not seem to work. May have to remove it.
merged in pr 66 prematurely. Please address comments: https://github.com/garageScript/databases/pull/66/files
Update user account lib/user.js
To document these changes: https://github.com/garageScript/databases/pull/21/files
hostname: 165.227.55.105
username: account username
password: account setDbPassword value
or
Create PG Credentials - Button
Postgres is an application. More specifically, a database application for you to organize your data. It can store data for you and you can have multiple apps connect to your Postgres:
To quickly help you get started, we will go over a few basic commands that you can follow along. Explanations and best practices will be covered in the section below.
To connect to your app to Postgres, you need a module called pg
. You need to specify where the postgres application is located (host and port), the name of your database, and your username / password to login to the database.
const { Client } = require('pg')
const startApp = async ()=>{
client = new Client({
host: '<host name>',
port: 5432,
user: '<username>',
password: '<password>',
database: '<database_name>'
})
await client.connect()
console.log('Connected')
}
startApp()
After connecting to Postgres, you can now send commands that Postgres can understand. These commands are called Sequel Query Language (SQL). Here are a few:
CREATE TABLE lesson( id serial PRIMARY KEY, title VARCHAR (256) );
lesson
that has 2 columns: id
and title
id
column is a primary key and the serial
property means that it will automatically increase as you add rows into the table.VARCHAR (256)
means that title is a string of up to 256 characters.INSERT INTO lesson (title) VALUES ('postgres tutorial')
lesson
table with a title of 'postgres tutorial'.select * from lesson where title = 'postgres tutorial'
"postgres tutorial'
.UPDATE lesson SET title = 'postgres demo' WHERE id=1;
id =1
, and then changes the title to 'postgres demo'
DELETE FROM lesson WHERE id=1;
id = 1
To run a Query, you run client.query(' -- YOUR SQL HERE --')
Make sure you await to resolve! All SQL commands involves sending a the SQL to your postgres application and then waiting for it to finish executing, so the commands will be asynchronous. Therefore any client actions will be asynchronous and returns a promise. To wait for a command to finish, you need an await
or .then
to wait for the query to resolve before continuing.
const lessons = await client.query('SELECT * from lesson;'); // gets all the lessons
console.log( lessons.rows )
How would you execute these commands in your website? Here are a few sample code to build an API:
app.post('/api/lessons', async (req, res) => {
await client.query(`INSERT INTO lesson (title) VALUES ($1)`, [req.body.title])
res.status(201).send('lesson created')
})
app.get('/api/lessons', async (req, res) => {
const lessons = await client.query(`select * from lesson;`)
res.json(lessons.rows)
})
app.get('/api/lessons/:id', async (req, res) => {
const lessons = await client.query(`select * from lesson WHERE id=$1;`, [req.params.id])
res.json(lessons.rows[0])
})
app.put('/api/lessons/:id', async (req, res) => {
const lessons = await client.query(`UPDATE lesson SET title = $1 WHERE id=$2;`, [req.body.title, req.params.id])
res.send('resource updated')
})
app.delete('/api/lessons/:id', async (req, res) => {
await client.query(`DELETE lesson WHERE id=$1;`, [req.params.id])
res.send('resource deleted')
})
Notice how we don't create a string from user input and directly execute that query like this:
client.query(`DELETE lesson WHERE id=${req.params.id};`)
If you create an SQL query directly from user input, your database will have a security issue called (Injection vulnerability). A user could simply pass in the following as id: 1; UPDATE lesson SET title="my awesome title" WHERE id=1
. The user could essentially do anything they want to your database, including deleting all your data.
To prevent this awful attack, always make sure to pass user input as the second argument into client.query
. The client.query
function will help you clean the user input to prevent sql injection attacks.
When it comes to Postgres and other SQL databases, you must be very intentional about your data and make sure it is clear and organized. If you are building a website like c0d3 and you have a user
table to store user information and a lesson
table to store lesson information (like title and description), how do you store the user's progress for each lesson?
Option1 Could you add a column to the user
table?
user
table.Option2 Could you add a column to the lesson
table?
lesson
table.Creating a new table. The best solution is to create a new table called userlesson
that has 3 columns:
userId
to retrieve user's information from the corresponding user
table when needed.lessonId
to retrieve lesson's information from the corresponding lesson
table when needed.status
that is a string, to store the user's status for the each lesson.In the above example, since userId
and lessonId
are used to retrieve the row from the user and lesson tables respectively, they are called foreign keys. userId
is a foreign key to the user
table.
The id
column in the user
and lesson
table that other tables reference to, is called the primary key. id
column is a primary key for the lesson (or user) table.
Let's say you want to see what the status is for lesson with id 5 for every user in your database. How would you do that?
Option 1 : Get all the users from your database and then get their lesson status for each user:
const users = await client.query(`select * from user;`)
const allStatuses = await Promise.all( users.rows.map( (user) => {
return client.query(`select * from userlesson WHERE userid=$1 AND lessonid=$2;`, [user.id, lessonId])
}))
Option 2: Run 1 query using join:
const result = client.query(`
SELECT
userlesson.status,
user.email,
FROM
userlesson
WHERE
userlesson.lessonid = $1
INNER JOIN user ON user.id = userlesson.userid
`, [lessonId])
Join helps you combine these tables together and get data from all the tables in 1 query. If you forget how to use Join, remember that you can always use option 1 to get the data you need by running multiple queries. To understand why you need join, let's analyze the two options above. Let's say:
userlesson
table has 7000 rows.Option1: 1000*7000 lookups. 7 Million lookups!
userlesson
table to find the correct userid
and lessonid
Option2: 7000 lookup + magic time
Postgres's magic time is really fast. Option 2 will be significantly faster than option 1 and with a big database it could mean the difference between waiting months and waiting minutes. If you are a data analyst, part of your job is to figure out how to join tables efficiently to get the data you need quickly.
Sometimes, you could unknowingly join tables in a way to make your query ALOT slower than option 1. The most painful part about this mistake is that when data is small, you don't notice the query taking a long time. However, as the company grows over the years and more data is accumulated, the code is forgotten and the application becomes really, really slow. This problem is very difficult to fix and to avoid writing joins directly, most companies use an Object Relational Mapping (ORM) library to generate the SQL queries for you. This not only avoids the problem of engineers joining the tables incorrectly but also allows developers to use the database without knowing SQL.
In the previous section, you learned how to directly connect to your postgres database, execute simple queries, and execute more complex queries using join. These SQL queries are hard to remember, manage, and could be written incorrectly to make the queries really slow. To solve these problems, most production systems use an Object Relational Mapping (ORM) library. We will use the most common one called sequelize in this section. Sequelize converts your JavaScript functions into SQL commands for you.
To use sequelize, you must first connect to your database and then create the necessary tables.
const { Sequelize, DataTypes } = require('sequelize')
// Defining your database connection
const sequelize = new Sequelize('database', 'username', 'password', {
host: '<host for database>',
dialect: 'postgres'
});
// Creating a table called lesson
const Lesson = await sequelize.define('lesson', {
title: {
type: DataTypes.STRING,
allowNull: false
}
})
await sequelize.sync({ alter: !!process.env.ALTER_DB })
await sequelize.authenticate()
// Update title
await Lessons.update( {
title: "new value"
}, {
where: { id: 1 }
})
await Lessons.destroy( {
where: { id: 1 }
})
await Lessons.findAll()
await Lessons.findAll( {
where: { id: 1 }
})
await Lessons.create({
title: 'new title'
})
in /lib/user.js
there should be a resetUserPassword
function.
Added github actions: https://github.com/garageScript/databases/pull/91/files
Builds are failing. Figure out why.
AC
createUser
, updateUserDBPassword
, confirmUserAccount
, createSession
Affects:
https://github.com/garageScript/databases/pull/108/files
Tutorial: https://scotch.io/tutorials/use-ejs-to-template-your-node-application
/views/partials
folder.<% include ../partials/head %>
As a engineer, I want to be able to look at my monitoring systems to make sure nothing is broken and set up alerts. For example, if database is down for some reason, I should get alerted right away.
If a user reports an issue, I should be able to look at the logs and figure out what the issue is.
Logging module must support these features:
logger.error(....)
logger.log(...)
For now our logging module can just use console.log
or console.error
const log = require('./log')(__filename)
log
, warn
, error
error
is used for alerts.warn
is used for analysis.log
is informational and debuggingpg
module to use logger module: https://github.com/garageScript/databases/pull/2/files/lib/user.js
should have a function called sendPwReset
{userId: id, userToken: token}
, then base64encode it.db.js
to have one to many relationships. User has many databases through UserDatabases.Updating db password
PATCH /api/users/:id
Acceptance:
startMongoDB
function must start the databasecloseMongoDB
function must close the databasecreateMongoDB
function must create an account.deleteMongoDB
function must delete an account.Create username and password and a submit button, add bootstrap to make it look nice.
Current progress: https://github.com/garageScript/databases/pull/2/files
Acceptance:
startPGDB
function must start the PG databaseclosePGDB
function must close the PG databasecreatePGAccount
function must create an account.deletePGAccount
function must delete an account.A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.