Youtube Clone Coding (7. Video Owner)

LeeJaeHoon·2021년 10월 25일
0
post-thumbnail
  1. video model에 owner 추가하기
    • ref는 어떤 mode의 id를 넣을 것 인지 설정 하는 것
      const videoSchema = new mongoose.Schema({
        fileUrl: { type: String, required: true },
        title: { type: String, required: true, trim: true, maxlength: 80 },
        description: { type: String, required: true, trim: true, minlength: 10 },
        createdAt: { type: Date, required: true, default: Date.now },
        hashtags: [{ type: String, trim: true }],
        meta: {
          views: { type: Number, default: 0, required: true },
          rating: { type: Number, default: 0, required: true },
        },
        owner: { type: mongoose.Schema.Types.ObjectId, required: true, ref: "User" },
      });
    • video를 upload한 owner만 edit/delete video를 볼 수 있게 설정하기.
      • video를 upload할때 postUpload controller에서 owner을 설정해 주어야함

        
        const {
            user: { _id },
          } = req.session;
        await Video.create({
              title,
              description,
              fileUrl,
              owner: _id,
              hashtags: Video.formatHashtags(hashtags),
            });
      • loggedInUser은 middleware으로 설정한 값임. (req.session.user)

      • loggedInUser._id와 video.owner은 서로 type이 달라 String으로 바꿔 줘야함.

        if String(loggedInUser._id) === String(video.owner)
            a(href=`${video.id}/edit`) Edit Video →
            br
            a(href=`${video.id}/delete`) Delete Video →
    • watch.pug에서 video를 upload한 사람 보여주게 설정하기.
      1. 첫번째 방법
        • watch controller에서 owner을 Userdb에서 가져온후 render로 pug에 보내준다.
          export const watch = async (req, res) => {
            const { id } = req.params;
            const video = await Video.findById(id);
            const owner = await User.findById(video.owner);
            if (!video) {
              return res.status(404).render("404", { pageTitle: "Video not found" });
            }
            return res.render("watch", { pageTitle: video.title, video, owner });
          };
        • watch.pug에 owner 변수 사용하기.
          div
              small Uploaded by #{owner.name}
      2. populate 사용하는 방법
        • video model에서 owner에 ref를 User으로 설정 해두어서 populate를 사용 할 수 있음.
          • populate를 설정하면 videodml owner에 user정보가 들어감

          • 밑의 코드는 populate한 video의 내용

            {
              meta: { views: 0, rating: 0 },
              _id: new ObjectId("6175061eeea27b4b08e9dd3f"),
              fileUrl: 'uploads/videos/0133df49bec4e9e7487960596dae8a9c',
              title: 'wqe',
              description: 'qwewwqewqeqwewq',
              hashtags: [ '#wetube', '#coding', '#js', '#ts' ],
              owner: {
                _id: new ObjectId("617505c656b9a7752860d587"),
                email: 'dlwogns3413@naver.com',
                avatarUrl: 'https://avatars.githubusercontent.com/u/62169861?v=4',
                socialOnly: true,
                username: 'abc5259',
                password: '$2b$05$PHglLSEBLvyVBEi0gqYQZ.7yuvB16BDWWifDeVejlsoDT5.GvrBg.',
                name: 'LeeJaeHoon',
                location: null,
                __v: 0
              },
              createdAt: 2021-10-24T07:07:10.918Z,
              __v: 0
            }
          • 밑의 코드는 populate하기 전 video의 내용

            {
              meta: { views: 0, rating: 0 },
              _id: new ObjectId("6175061eeea27b4b08e9dd3f"),
              fileUrl: 'uploads/videos/0133df49bec4e9e7487960596dae8a9c',
              title: 'wqe',
              description: 'qwewwqewqeqwewq',
              hashtags: [ '#wetube', '#coding', '#js', '#ts' ],
              owner: new ObjectId("617505c656b9a7752860d587"),
              createdAt: 2021-10-24T07:07:10.918Z,
              __v: 0
            }
        • watch controller의 내용
          • populate의 인자로는 Video Model에 설정해둔 owner이 들어가야함

            export const watch = async (req, res) => {
              const { id } = req.params;
              const video = await Video.findById(id).populate("owner");
              console.log(video);
              if (!video) {
                return res.status(404).render("404", { pageTitle: "Video not found" });
              }
              return res.render("watch", { pageTitle: video.title, video });
            };
        • watch.pug에 video 변수 사용하기
          div
              small Uploaded by 
                a(href=`/users/${video.owner._id}`)  #{video.owner.name}
          if String(loggedInUser._id) === String(video.owner._id)
              a(href=`${video.id}/edit`) Edit Video →
              br
              a(href=`${video.id}/delete`) Delete Video →
  2. User에 videos추가하기
    • 한명의 user은 여러개의 video를 가지고 있으니 배열에 담아준다.
      const userSchema = new mongoose.Schema({
        email: { type: String, required: true, unique: true },
        avatarUrl: { type: String },
        socialOnly: { type: Boolean, default: false },
        username: { type: String, required: true, unique: true },
        password: { type: String },
        name: { type: String, required: true },
        location: { type: String },
        videos: [{ type: mongoose.Schema.Types.ObjectId, ref: "Video" }],
      });
    • video를 create힐떼미디 민들어진 video의 id를 user.videos에 추가한다.
      • create 메소드는 새로만들어진 video를 리턴한다.

        export const postUpload = async (req, res) => {
          const {
            user: { _id },
          } = req.session;
          const { path: fileUrl } = req.file;
          const { title, description, hashtags } = req.body;
          try {
            const newVideo = await Video.create({
              title,
              description,
              fileUrl,
              owner: _id,
              hashtags: Video.formatHashtags(hashtags),
            });
            const user = await User.findById(_id);
            user.videos.push(newVideo._id);
            user.save();
            return res.redirect("/");
          } catch (error) {
            return res.status(400).render("upload", {
              pageTitle: `Upload Video`,
              errorMessage: error._message,
            });
          }
        };
      • user.save()를 할때마다 User에 설정해둔 middleware(비밀번호 hash)가 발생하므로 추가적인 코드를 작성 해주어야 한다.

      • isModified메소드는 인자에 바뀌는 것을 넣고 바뀌면 true를 리턴해줌.

        userSchema.pre("save", async function () {
          //this는 create되는 User을 가리킴
          if (this.isModified("password")) {
            this.password = await bcrypt.hash(this.password, 5);
          }
        });
    • see controller에서 user을 가져올때 populate를 사용하여 videos의 내용을 볼 수 있게 설정한다.
      export const see = async (req, res) => {
        const { id } = req.params;
        const user = await User.findById(id).populate("videos");
        if (!user) {
          return res.status(404).render("404", { pageTitle: "User not found." });
        }
        return res.render("users/profile", {
          pageTitle: `${user.name} Profile`,
          user,
        });
      };
      • populate를 쓰지 않았을 때 user의 내용
        {
          _id: new ObjectId("6175756c40a60952e39093ae"),
          email: 'dlwogns3413@naver.com',
          avatarUrl: 'https://avatars.githubusercontent.com/u/62169861?v=4',
          socialOnly: true,
          username: 'abc5259',
          password: '$2b$05$0IetvgkbDNZZYbgHN4Di3uKIIDjYZilaPdpkNxOJXf45o146oTaDm',
          name: 'LeeJaeHoon',
          location: null,
          videos: [ new ObjectId("6175757b40a60952e39093b1") ],
          __v: 1
        }
      • populate를 썻을 때 user의 내용
        {
          _id: new ObjectId("6175756c40a60952e39093ae"),
          email: 'dlwogns3413@naver.com',
          avatarUrl: 'https://avatars.githubusercontent.com/u/62169861?v=4',
          socialOnly: true,
          username: 'abc5259',
          password: '$2b$05$0IetvgkbDNZZYbgHN4Di3uKIIDjYZilaPdpkNxOJXf45o146oTaDm',
          name: 'LeeJaeHoon',
          location: null,
          videos: [
            {
              meta: [Object],
              _id: new ObjectId("6175757b40a60952e39093b1"),
              fileUrl: 'uploads/videos/6e4d8b7b59e2799c82f3a2011a19a5a6',
              title: 'wq',
              description: 'good Defaultwqeqw',
              hashtags: [Array],
              owner: new ObjectId("6175756c40a60952e39093ae"),
              createdAt: 2021-10-24T15:02:19.879Z,
              __v: 0
            }
          ],
          __v: 1
        }
    • 로그인이 된 상태에서 video owner이 아닌데 video edit/delete되는 버그 고치기
      • req.sessino에서 가져온 _id와 video.owner을 비교해서 다르면 home으로 redirect되게 설정
        • 둘이 type이 달라 String으로 변환 해 주어야 함.

          if (String(video.owner) !== String(_id)) {
              return res.status(403).redirect("/");
            }
      • deleteVideo에서 만약 video가 delete됐을때 user.videos에서도 삭제된 video를 삭제해야함
        user.videos.splice(user.videos.indexOf(id), 1);
          user.save();

0개의 댓글