[MERN③] Profile API Routes

~~~~~~~~~~ (Contents) MERN ~~~~~~~~~~~
[MERN①] Express & MongoDB Setup
https://qiita.com/niyomong/private/3281af84486876f897f7
[MERN②]User API Routes & JWT Authentication
https://qiita.com/niyomong/private/c11616ff7b64925f9a2b
[MERN③] Profile API Routes
https://qiita.com/niyomong/private/8cff4e6fa0e81b92cb49
[MERN④] Post API
https://qiita.com/niyomong/private/3ce66f15375ad04b8989
[MERN⑤] Getting Started With React & The Frontend
https://qiita.com/niyomong/private/a5759e2fb89c9f222b6b
[MERN⑥] Redux Setup & Alerts
https://qiita.com/niyomong/private/074c27259924c7fd306b
[MERN⑦] React User Authentication
https://qiita.com/niyomong/private/37151784671eff3b92b6
[MERN⑧] Dashboard & Profile Management
https://qiita.com/niyomong/private/ab7e5da1b1983a226aca
[MERN⑨] Profile Display
https://qiita.com/niyomong/private/42426135e959c7844dcb
[MERN⑩] Posts & Comments
https://qiita.com/niyomong/private/19c78aea482b734c3cf5
[MERN11] デプロイ
https://qiita.com/niyomong/private/150f9000ce51548134ad
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

##1. Profile Modelを作成

[String] <= これは配列

```models/Profile.js
const mongoose = require('mongoose');

const ProfileSchema = new mongoose.Schema({
  user: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'user',
  },
  status: {
    type: String,
  },
  website: {
    type: [String],
  },
  bio: {
    type: String,
  },
  social: [
    {
      youtube: {
        type: String,
      },
      twitter: {
        type: String,
      },
      facebook: {
        type: String,
      },
      linkedin: {
        type: String,
      },
    },
  ],
  date: {
    type: Date,
    default: Date.now,
  },
});

module.exports = Profile = mongoose.model('profile', ProfileSchema);

```

##2. Get Current user Profile

```routes/api/profile.js
const express = require('express');
const router = express.Router();
const auth = require('../../middleware/auth');

const Profile = require('../../models/Profile');
const User = require('../../models/User');

// @route  GET api/profile/me
// @desc   Get current users profile
// @access Private
router.get('/me', auth, async (req, res) => {
  try {
    const profile = await Profile.findOne({
      user: req.user.id,
    }).populate('user', ['name', 'avatar']);

    if (!profile) {
      return res.status(400).json({ msg: 'There is no profile for this user' });
    }

    res.json(profile);
  } catch (err) {
    console.error(err.message);
    res.status(500).send('Server Error');
  }
});

module.exports = router;

```

##3. Create & Update Profile Routes

```routes/api/profile.js
const express = require('express');
const router = express.Router();
const auth = require('../../middleware/auth');
+ const { body, validationResult } = require('express-validator');

const Profile = require('../../models/Profile');
const User = require('../../models/User');

// @route  GET api/profile/me
// @desc   Get current users profile
// @access Private
router.get('/me', auth, async (req, res) => {
  try {
    const profile = await Profile.findOne({
      user: req.user.id,
    }).populate('user', ['name', 'avatar']);

    if (!profile) {
      return res.status(400).json({ msg: 'There is no profile for this user' });
    }
  } catch (err) {
    console.error(err.message);
    res.status(500).send('Server Error');
  }
});

以下、追加！！
// @route  POST api/profile
// @desc   Create or update user profile
// @access Private
router.post(
  '/',
  [
    auth,
    [
      body('status', 'Status is required').not().isEmpty(),
      body('skills', 'Skills is not require').not().isEmpty(),
    ],
  ],
  async (req, res) => {
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      return res.status(400).json({ errors: errors.array() });
    }
    const {
      status,
      skills,
      bio,
      website,
      youtube,
      twitter,
      facebook,
      linkedin,
    } = req.body;

    // Build profile object
    const profileFields = {};
    profileFields.user = req.user.id;
    if (status) {
      profileFields.status = status.split(',').map((status) => status.trim());
    }
    if (skills) {
      profileFields.skills = skills.split(',').map((skill) => skill.trim());
    }
    if (bio) profileFields.bio = bio;
    if (website) profileFields.website = website;

    // Build social object
    profileFields.social = {};
    if (youtube) profileFields.social.youtube = youtube;
    if (twitter) profileFields.social.twitter = twitter;
    if (facebook) profileFields.social.facebook = facebook;
    if (linkedin) profileFields.social.linkedin = linkedin;

    try {
      let profile = await Profile.findOne({ user: req.user.id });

      if (profile) {
        // Update
        profile = await Profile.findOneAndUpdate(
          { user: req.user.id },
          { $set: profileFields },
          { new: true }
        );

        return res.json(profile);
      }
      // Create
      profile = new Profile(profileFields);

      await profile.save();
      res.json(profile);
    } catch (err) {
      console.error(err.message);
      res.status(500).send('Server Error');
    }
  }
);

module.exports = router;

```

POSTMANで確認
![スクリーンショット 2020-09-06 22.37.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294859/f0f74517-0364-884d-65f7-d5eaf7c9cee4.png)

##4. Get All Profiles & Profile By User ID

```routes/api/profile.js
...
// @route  GET api/profile
// @desc   Get all profiles
// @access Public
router.get('/', async (req, res) => {
  try {
    const profiles = await Profile.find().populate('user', ['name', 'avatar']);
    res.json(profiles);
  } catch (err) {
    console.error(err.profileFields);
    res.status(500).send('Server Error');
  }
});

// @route  GET api/profile/user/:user_id
// @desc   Get profiles by user ID
// @access Public
router.get('/user/:user_id', async (req, res) => {
  try {
    const profile = await Profile.findOne({
      user: req.params.user_id,
    }).populate('user', ['name', 'avatar']);

    if (!profile) return res.status(400).json({ msg: 'Profile not found' });

    res.json(profile);
  } catch (err) {
    console.error(err.message);
    if (err.kind == 'ObjectId') {
      return res.status(400).json({ msg: 'Profile not found' });
    }
    res.status(500).send('Server Error');
  }
});

module.exports = router;

```

##5. Delete Profile & User

```routes/api/profile.js
...
// @route  DELETE api/profile
// @desc   Delete profile, user & posts
// @access Private
router.delete('/', auth, async (req, res) => {
  try {
    // @todo - remove users posts

    // Remove profile
    await Profile.findOneAndRemove({ user: req.user.id });
    // Remove user
    await User.findOneAndRemove({ _id: req.user.id });

    res.json({ msg: 'User deleted' });
  } catch (err) {
    console.error(err.message);
    res.status(500).send('Server Error');
  }
});
...
```