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

env配置

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

修改next.config.mjs

js 复制代码
/** @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依赖:

shell 复制代码
pnpm i mongoose 

新建lib/db.js

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

js 复制代码
import mongoose from 'mongoose'

const userSchema = new mongoose.Schema({
  name: { type: String, require: true },
  email: { type: String, require: true, unique: true },
  password: { type: String, require: 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依赖:

shell 复制代码
pnpm i jsonwebtoken

新建utils/generateToken.js

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

js 复制代码
import { NextResponse } from 'next/server'

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

实现loginregister API

安装bcrypt依赖:

shell 复制代码
pnpm i bcrypt

新建app/auth/login/route.js

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

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)
  }
}

结果如下:

相关推荐
_xaboy9 分钟前
开源Vue组件FormCreate通过 JSON 生成TinyVue表单
前端·vue.js·低代码·开源·json·表单设计器
ZC跨境爬虫15 分钟前
跟着 MDN 学CSS day_44:响应式设计——让网页适配所有屏幕的完整指南
前端·css·ui·html·tensorflow
前端不太难23 分钟前
Edge AI 时代:从数据中心到终端,算力如何无处不在?
前端·人工智能·edge
Highcharts.js24 分钟前
Highcharts v13 全新时间轴标签边界格式|让时间维度表达更智能
前端·信息可视化·时间序列·图表开发·chart·自定义标签·可视化开发
lichenyang45325 分钟前
鸿蒙研读 10:@Provider/@Consumer、RelativeContainer、onNewWant
前端
大湿兄啊啊啊30 分钟前
MID360S调试
java·服务器·前端
绺年32 分钟前
模块化加载机制与循环依赖的探索
前端
Csvn41 分钟前
前端技术 - 前端技术债务
前端
Days20501 小时前
Flyfish Viewer:全能纯前端多格式文件预览组件,解锁浏览器端无门槛预览新体验
前端
selfsuer1 小时前
【奇奇怪怪前端问题记录】
前端