likes
comments
collection
share

「2」next-shopping:数据库+登录注册

作者站长头像
站长
· 阅读数 6

env配置

我们可以在next.config.mjs中的nextConfig对象下面,直接设置env对象,这样就可以在tsx中通过process.env.xxx获取

修改next.config.mjs

/** @type {import('next').NextConfig} */
const nextConfig = {
  env: {
    BASE_URL: 'http://localhost:3000',
    MONGODB_URL: 'mongodb://root:123456@127.0.0.1:27017/next-shopping',
    ACCESS_TOKEN_SECRET: '1233211234567890',
    REFRESH_TOKEN_SECRET: '987654321',
  },
}

export default nextConfig

数据库函数

本项目采用的是mongodb数据库,所以可以使用monoose依赖:

pnpm i mongoose 

新建lib/db.js

import mongoose from 'mongoose'

const connection = {}

async function connect() {
  if (connection.isConnected) {
    console.log('already connected')
    return
  }
  if (mongoose.connections.length > 0) {
    connection.isConnected = mongoose.connections[0].readyState
    if (connection.isConnected === 1) {
      console.log('use previous connection')
      return
    }
    await mongoose.disconnect()
  }

  try {
    console.log('process.env.MONGODB_URL', process.env.MONGODB_URL)
    const db = await mongoose.connect(process.env.MONGODB_URL)
    console.log('new connection')
    connection.isConnected = db.connections[0].readyState
  } catch (error) {
    console.log(error)
    process.exit(1)
  }
}

async function disconnect() {
  if (connection.isConnected) {
    if (process.env.NODE_ENV === 'production') {
      await mongoose.disconnect()
      connection.isConnected = false
    } else {
      console.log('not disconnected')
    }
  }
}

const db = { connect, disconnect }
export default db

用户模块

创建models/user.js

import mongoose from 'mongoose'

const userSchema = new mongoose.Schema({
  name: { type: String, required: true },
  email: { type: String, required: true, unique: true },
  password: { type: String, required: true },
  role: { type: String, default: 'user' },
  root: { type: Boolean, default: false },
  avatar: {
    type: String,
    default:
      'https://images.pexels.com/photos/17022636/pexels-photo-17022636.jpeg?auto=compress&cs=tinysrgb&w=800&lazy=load',
  },
})

const User = mongoose.models.user || mongoose.model('user', userSchema)

export default User

实现token函数

下载jsonwebtoken依赖:

pnpm i jsonwebtoken

新建utils/generateToken.js

import jwt from 'jsonwebtoken'

export const createAccessToken = payload => {
  return jwt.sign(payload, process.env.ACCESS_TOKEN_SECRET, {
    expiresIn: '15min',
  })
}

export const createRefreshToken = payload => {
  return jwt.sign(payload, process.env.REFRESH_TOKEN_SECRET, {
    expiresIn: '7d',
  })
}

新建utils/sendError.js

import { NextResponse } from 'next/server'

export default function sendError(status, msg) {
  return NextResponse.json({ err: msg }, { status: status })
}

实现loginregister API

安装bcrypt依赖:

pnpm i bcrypt

新建app/auth/login/route.js

import { NextResponse } from 'next/server'
import bcrypt from 'bcrypt'

import db from '@/lib/db'
import Users from '@/models/User'
import sendError from '@/utils/sendError'
import { createAccessToken, createRefreshToken } from '@/utils/generateToken'

export async function POST(req) {
  try {
    await db.connect()
    const { email, password } = await req.json()

    const user = await Users.findOne({ email })

    if (!user) return sendError(400, '找不到此电子邮件的应用程序')

    const isMatch = await bcrypt.compare(password, user.password)

    if (!isMatch) return sendError(400, '电子邮件地址或密码不正确')

    const access_token = createAccessToken({ id: user._id })
    const refresh_token = createRefreshToken({ id: user._id })

    return NextResponse.json(
      {
        msg: '登录成功',
        refresh_token,
        access_token,
        user: {
          name: user.name,
          email: user.email,
          role: user.role,
          avatar: user.avatar,
          root: user.root,
        },
      },
      { status: 200 }
    )
  } catch (error) {
    console.log('====error====', error.message)
    return sendError(500, error.message)
  }
}

新建app/auth/register/route.js

import { NextResponse } from 'next/server'
import bcrypt from 'bcrypt'

import db from '@/lib/db'
import Users from '@/models/User'
import sendError from '@/utils/sendError'

export async function POST(req, { params }) {
  try {
    await await db.connect()
    const { name, email, password } = await req.json()

    const user = await Users.findOne({ email })

    if (user) return sendError(400, '该账户已存在')

    const hashPassword = await bcrypt.hash(password, 12)
    const newUser = new Users({ name, email, password: hashPassword })
    await newUser.save()
    await db.disconnect()

    return NextResponse.json(
      {
        meg: '注册成功',
      },
      {
        status: 201,
      }
    )
  } catch (error) {
    return sendError(500, error.message)
  }
}

结果如下:

「2」next-shopping:数据库+登录注册