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

结果如下:

相关推荐
小二·4 分钟前
Python Web 开发进阶实战:AI 伦理审计平台 —— 在 Flask + Vue 中构建算法偏见检测与公平性评估系统
前端·人工智能·python
走粥12 分钟前
选项式API与组合式API的区别
开发语言·前端·javascript·vue.js·前端框架
We་ct15 分钟前
LeetCode 12. 整数转罗马数字:从逐位实现到规则复用优化
前端·算法·leetcode·typescript
方安乐23 分钟前
react笔记之useMemo
前端·笔记·react.js
晚霞的不甘27 分钟前
解决 Flutter for OpenHarmony 构建失败:HVigor ERROR 00303168 (SDK component missing)
android·javascript·flutter
清风细雨_林木木31 分钟前
react 中 form表单提示
前端·react.js·前端框架
小二·39 分钟前
Python Web 开发进阶实战:边缘智能网关 —— 在 Flask + MicroPython 中构建轻量级 IoT 边缘推理平台
前端·python·flask
TOPGUS40 分钟前
解析200万次对话数据:ChatGPT引用内容的核心特征与优化策略
前端·人工智能·搜索引擎·chatgpt·seo·数字营销
羊仔AI探索1 小时前
前端已死,未来已来,谷歌Gemini 3 Pro杀回来了!
前端·人工智能·ai·aigc
2501_944521591 小时前
Flutter for OpenHarmony 微动漫App实战:分享功能实现
android·开发语言·javascript·flutter·ecmascript