omarokasha1 / TheFirstProject

This is a Learning Management System Solutions Developed from Scratch inside Orange Digital Center Labs By ODC-Flutter WorkForce.
https://www.orangedigitalcenters.com/country/EG/home
10 stars 6 forks source link

Learning Process : Backend #3

Open omarokasha1 opened 2 years ago

omarokasha1 commented 2 years ago

Please Keep Daily Documenting your Learning Process Here.

omarokasha1 commented 2 years ago

We need to Document ( Installation - Usage - Hello World Example - Links for DOcumentation for each one ) : 1)Node JS Installation  https://nodejs.org/en/docs/guides/getting-started-guide/ node 1 node 2 node 3

1) Express JS Installation  • mkdir myapp • cd myapp • npm init • npm install express –save Hello world Example https://expressjs.com/en/starter/hello-world.html express

2) MongoDB Installation for ubuntu • wget -qO - https://www.mongodb.org/static/pgp/server-5.0.asc | sudo apt-key add - • sudo apt-get install gnupg • echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/5.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-5.0.list • sudo apt-get update • sudo apt-get install -y mongodb-org

Installation for windows • https://docs.mongodb.com/manual/tutorial/install-mongodb-on-windows/

3) IDEs

omarokasha1 commented 2 years ago

@omda07 We need to invest more in the documentation Omda, This is one of the most important Issues to see it is documentation .

For Examples for some Questions Must be Asked and Answered :

1) Which libraries you used through the development process? 2) From Where you start to Learn these tools? 3) You need to document in the code how to manipulate this code to for example change the Registeration from Email usage to Phone Number Usage ? if we want to depend on For example just username Registeration ? How can we start Handling the Dabatase ?

We need to ensure through your learning Journey That your Friends @KareemAhmed22 @mariamyoussefwiliam @mirette3 @AsimAyman @youssefelgebaly Can start how can edit in the backend through just your Documetnation and can understand this code .

These are just a suggestion Question If you didn't document Day by Day you will lose the track of Documentation Everything.

@mirette3 : I will follow up with you to ensure that the documentation for the backend is up and Running by the end of tomorrow Even if We stop Development and Finalizing all Documentation Needed to be on track of Documentation .

That is all for Now.

omda07 commented 2 years ago

From Where you start to Learn these tools?

Tutorial Node js
Documentation Node js Docs

Tutorial Express js Documentation Express js Docs

Arabic tutorial API Tutorial
English Crash Course API Tutorial en

Which libraries you used through the development process?

Structure of code

there are 5 folders

HTTP response status codes

// copmresed requests app.use(compression())

// import register const usersRegister = require('./routes/register') app.use('/register', usersRegister) // import login const usersLogin = require('./routes/login') app.use('/login', usersLogin) // import profile const userProfile = require('./routes/profile') app.use('/profile', userProfile) // import changepassword const changePassword = require('./routes/changePassword') app.use('/api/changePassword', changePassword) // import courses const newCourse = require('./routes/courses') app.use('/api/course', newCourse)

// if write invalide url or end point send to user an error message app.all('*', (req, res, next) => { res.status(404).json({ status: 'false', message: 'Page not found !' }) }) // listen on port 8080 local host app.listen(8080, () => logger.info('server started 8080 ....'))


# Build User Schema 
###### You can add or remove any attribute
- userName must be in lowercase to be unique and make all users name completely different   
```sh
const UserSchema = new mongoose.Schema({
    userName: { type: String,unique:true, required: true, lowercase:true,minlength: 3, maxlength: 44 },
    email: { type: String, required: true, maxlength: 254 },
    password: { type: String, required: true, minlength: 8, maxlength: 1024 },
    phone: { type: Number, unique: true, minlength: 11, maxlength: 11 },
    isAdmin: { type: Boolean }m
 userEducation:  {
        university: { type: String, },
        major: { type: String, },
        faculty: { type: String, },
        experince: { type: String, },
        grade: { type: String, },
        interest: 
            [{type:String}]

    } ,
})

Schema validation using joi package

You can add or remove any attribute from your schema

}


```sh
//*validation on user inputs in login
function validateUserLogin(user) {
    const JoiSchema = Joi.object({

        email: Joi.string().email().min(3).max(25).required(),

        password: Joi.string().min(8).max(512).required()

    }).options({ abortEarly: false });

    return JoiSchema.validate(user)
}

Build Registration

if (user) { return res.status(200).json({ status: 'false', message: 'email already in use' }) }

- You can change any required attribute form schema the change the message
```sh
let user = await Users.findOne({ userName }).lean()

if (user) {
return res.status(200).json({ status: 'false', message: 'userName already in use' })
}

Build Login

module.exports =function (req, res, next) {
    // get the token from header called x-auth-token 
    const token = req.header('x-auth-token')
    if (!token) {
        res.status(401).send('access denied not auth......')
    }

    try {
        // decode the token to get the user info using `jwt.verify` from package jsonwebtoken
        const decodeToken = jwt.verify(token, 'privateKey')
        req.user = decodeToken
        next()

    } catch (er) {
        res.status(400).send('wrong token ......')
    }
}

getCourses middleware

module.exports = async function getCourses(req, res, next) {
    let course
    try {
 // find the courses with author
      course = await Course.find().populate('author','-__V').select('-__v')
      if (!course) {
        return res.status(200).json({ status: 'false', message: 'Cannot find courses' })
      }
      res.course = course
    } catch (err) {
      return res.status(500).json({ message: err.message })
    }

    res.course = course
    next()
  }

Change Password

change password inside the app for user that logged in

router.post('/', async (req, res) => {
    // take the password from user and validate it
    const { password: plainTextPassword } = req.body

    // take the token from header
    const token = req.header('x-auth-token')

    // validate the password if not string
    if (!plainTextPassword || typeof plainTextPassword !== 'string') {
        return res.status(200).json({ status: 'false', message: 'Invalid password' })
    }
    // validate the password if less than 8 char
    if (plainTextPassword.length < 8) {
        return res.status(200).json({
            status: 'false',
            message: 'Password too small. Should be atleast 8 characters'
        })
    }

    try {
        // decode the token to get user data
        const user = jwt.verify(token, 'privateKey')
        console.log(user)

        // get user id 
        const id = user.id
        console.log(id)

        // incrypt new password
        const newPassword = await bcrypt.hash(plainTextPassword, 10)

        // find the user by id and change the password
        await User.updateOne(
            { _id: id },
            {
                $set: { password: newPassword }
            }
        )
        res.status(200).json({ status: 'ok', message: 'password changed' })
    } catch (error) {
        res.json({ status: 'false', message: error.message })
    }
})

Build Profile

middleware auth check first if user logged in and have a token

get('/', auth, async (req, res) => {
    // find the user info by his id and not show the password at response using `select`
    const profile = await User.findById(req.user.id).select('-password -__v')

    res.json({ profile })
})

Build Course Schema

# Build Get Courses 

```sh
// Getting all
//* using getcourses middleware
router.get('/',getCourses, async (req, res) => {
  res.status(200).json({status : "ok",courses:res.course})
})
omarokasha1 commented 2 years ago

@omda07 I am still waiting as we agreed yesterday to have some Examples based on each questions to understand what exactly to change for example :

check in database by any required attribute you want from schema for example by email let user = await Users.findOne({ email }).lean()

if (user) { return res.status(404).json({ status: 'false', message: 'email already in use' }) }

You can make it like :

let user = await Users.findOne({ username }).lean()

if (user) { return res.status(404).json({ status: 'false', message: 'email already in use' }) }

To change the feedback message you can change here from

if (user) { return res.status(404).json({ status: 'false', message: 'email already in use' }) }

to if (user) { return res.status(404).json({ status: 'false', message: 'Hi, This is an Error' }) }


What is the 10 here ? You need to clear in the comments of the code what is each value refer to


userName: { type: String, required: true, minlength: 3, maxlength: 44 }, email: { type: String, required: true, maxlength: 254 },

How can I add more validation to ensure for example : 1) the Username can't start with Sympols or Numbers 2) Username can't have spaces 3) Username can't be duplicated like email Live while I am writing on Flutter GUI I validate if this username is used before In the database or not . To make it more clear I am writing first char "O" this less than 3 Paramters the FLutter Team will Raise flag that is less than 3 Char but after haveing for example "OOO" how we check instant without click on registration button and send that this username is booked from example . 4) In username is "OOO" is different from "ooo" is the validation function compare with taking in consideration the Capital of the Chars ?


}).options({ abortEarly: false });

What is this line refer to ?


https://github.com/omarokasha1/TheFirstProject/blob/186e8bbef167fa6f0cbbd9b7fcc79bffa3498e77/loginAndRegister/server.js

Where is the documentation / Comments for this Code ?


After Have a some time in the backend code here is my Thoughts :

It is Very Important @omda07 and @mirette3 to have next Documentation : 1) What is the Structure of the Code 2) What is automatic Generated by tools and We didn't edit or Developed anything at and What we changed in some files and what we developed ? 3) I can see that in this path https://github.com/omarokasha1/TheFirstProject/tree/backend/loginAndRegister we have 5 Folders and 5 FIles what is the usage from each one ? 4) What is these status Numbers ? What are they referring to ? we need a table with the definition of each number . 5) We need a table of definition that will have a keyword like subscriber ? 6) Check Change Password Code , you need to make a lot of comments with some questions like :

Again @omda07 and @mirette3 We need to have a skill called beginner mindset that will enable us to help others understand the code without making them study everything to can easily make all possible edits .

**### _

_**

youssefelgebaly commented 2 years ago

Great job Ahmed, please add a method to install this project and how to Run the project on a local Server

download backend project

Import Backend project to Visual studio code IDE

  1. Open Visual studio code IDE.
    • FileOpenFloderChoosing the project from the device
  2. Click project to import to Visual studio code

Run the project on a local Server