新增支持API添加用户,查询邮件

This commit is contained in:
eoao
2025-08-10 11:37:46 +08:00
parent 2437ff4599
commit 46127a8d67
38 changed files with 894 additions and 713 deletions

View File

@@ -152,6 +152,10 @@ const accountService = {
await orm(c).insert(account).values({ ...params }).returning();
},
async insertList(c, list) {
await orm(c).insert(account).values(list).run();
},
async physicsDeleteAll(c) {
const accountIdsRow = await orm(c).select({accountId: account.accountId}).from(account).where(eq(account.isDel,isDel.DELETE)).limit(99);
if (accountIdsRow.length === 0) {

View File

@@ -119,10 +119,10 @@ const loginService = {
const userId = await userService.insert(c, { email, regKeyId,password: hash, salt, type: type || defType });
await userService.updateUserInfo(c, userId, true);
await accountService.insert(c, { userId: userId, email, name: emailUtils.getName(email) });
await userService.updateUserInfo(c, userId, true);
if (regKey !== settingConst.regKey.CLOSE && type) {
await regKeyService.reduceCount(c, code, 1);
}
@@ -136,6 +136,10 @@ const loginService = {
},
async registerVerify() {
},
async handleOpenRegKey(c, regKey, code) {
if (!code) {

View File

@@ -0,0 +1,195 @@
import BizError from '../error/biz-error';
import orm from '../entity/orm';
import { v4 as uuidv4 } from 'uuid';
import { and, asc, desc, eq, sql } from 'drizzle-orm';
import saltHashUtils from '../utils/crypto-utils';
import cryptoUtils from '../utils/crypto-utils';
import emailUtils from '../utils/email-utils';
import roleService from './role-service';
import verifyUtils from '../utils/verify-utils';
import { t } from '../i18n/i18n';
import reqUtils from '../utils/req-utils';
import dayjs from 'dayjs';
import { isDel, roleConst } from '../const/entity-const';
import email from '../entity/email';
import userService from './user-service';
import KvConst from '../const/kv-const';
const publicService = {
async emailList(c, params) {
let { toEmail, content, subject, sendName, sendEmail, timeSort, num, size, type , isDel } = params
const query = orm(c).select({
emailId: email.emailId,
sendEmail: email.sendEmail,
sendName: email.name,
subject: email.subject,
toEmail: email.toEmail,
toName: email.toName,
type: email.type,
createTime: email.createTime,
content: email.content,
text: email.text,
isDel: email.isDel,
}).from(email)
if (!size) {
size = 20
}
if (!num) {
num = 1
}
size = Number(size);
num = Number(num);
num = (num - 1) * size;
let conditions = []
if (toEmail) {
conditions.push(sql`${email.toEmail} COLLATE NOCASE LIKE ${toEmail}`)
}
if (sendEmail) {
conditions.push(sql`${email.sendEmail} COLLATE NOCASE LIKE ${sendEmail}`)
}
if (sendName) {
conditions.push(sql`${email.name} COLLATE NOCASE LIKE ${sendName}`)
}
if (subject) {
conditions.push(sql`${email.subject} COLLATE NOCASE LIKE ${subject}`)
}
if (content) {
conditions.push(sql`${email.content} COLLATE NOCASE LIKE ${content}`)
}
if (type || type === 0) {
conditions.push(eq(email.type, type))
}
if (isDel || isDel === 0) {
conditions.push(eq(email.isDel, isDel))
}
if (conditions.length === 1) {
query.where(...conditions)
} else if (conditions.length > 1) {
query.where(and(...conditions))
}
if (timeSort === 'asc') {
query.orderBy(asc(email.emailId));
} else {
query.orderBy(desc(email.emailId));
}
return query.limit(size).offset(num);
},
async addUser(c, params) {
const { list } = params;
if (list.length === 0) return;
for (const emailRow of list) {
if (!verifyUtils.isEmail(emailRow.email)) {
throw new BizError(t('notEmail'));
}
if (!c.env.domain.includes(emailUtils.getDomain(emailRow.email))) {
throw new BizError(t('notEmailDomain'));
}
const { salt, hash } = await saltHashUtils.hashPassword(
emailRow.password || cryptoUtils.genRandomPwd()
);
emailRow.salt = salt;
emailRow.hash = hash;
}
const activeIp = reqUtils.getIp(c);
const { os, browser, device } = reqUtils.getUserAgent(c);
const activeTime = dayjs().format('YYYY-MM-DD HH:mm:ss');
const roleList = await roleService.roleSelectUse(c);
const defRole = roleList.find(roleRow => roleRow.isDefault === roleConst.isDefault.OPEN);
const userList = [];
for (const emailRow of list) {
let { email, hash, salt, roleName } = emailRow;
let type = defRole.roleId;
if (roleName) {
const roleRow = roleList.find(role => role.name === roleName);
type = roleRow ? roleRow.roleId : type;
}
const userSql = `INSERT INTO user (email, password, salt, type, os, browser, active_ip, create_ip, device, active_time, create_time)
VALUES ('${email}', '${hash}', '${salt}', '${type}', '${os}', '${browser}', '${activeIp}', '${activeIp}', '${device}', '${activeTime}', '${activeTime}')`
const accountSql = `INSERT INTO account (email, name, user_id)
VALUES ('${email}', '${emailUtils.getName(email)}', 0);`;
userList.push(c.env.db.prepare(userSql));
userList.push(c.env.db.prepare(accountSql));
}
userList.push(c.env.db.prepare(`UPDATE account SET user_id = (SELECT user_id FROM user WHERE user.email = account.email) WHERE user_id = 0;`))
try {
await c.env.db.batch(userList);
} catch (e) {
if(e.message.includes('SQLITE_CONSTRAINT')) {
throw new BizError(t('emailExistDatabase'))
} else {
throw e
}
}
},
async genToken(c, params) {
await this.verifyUser(c, params)
const uuid = uuidv4();
await c.env.kv.put(KvConst.PUBLIC_KEY, uuid, { expirationTtl: 60 * 60 * 24 * 7 });
return {token: uuid}
},
async verifyUser(c, params) {
const { email, password } = params
const userRow = await userService.selectByEmailIncludeDel(c, email);
if (email !== c.env.admin) {
throw new BizError(t('notAdmin'));
}
if (!userRow || userRow.isDel === isDel.DELETE) {
throw new BizError(t('notExistUser'));
}
if (!await cryptoUtils.verifyPassword(password, userRow.salt, userRow.password)) {
throw new BizError(t('IncorrectPwd'));
}
}
}
export default publicService

View File

@@ -116,7 +116,7 @@ const roleService = {
},
roleSelectUse(c) {
return orm(c).select({ name: role.name, roleId: role.roleId }).from(role).orderBy(asc(role.sort)).all();
return orm(c).select({ name: role.name, roleId: role.roleId, isDefault: role.isDefault }).from(role).orderBy(asc(role.sort)).all();
},
async selectDefaultRole(c) {
@@ -170,6 +170,10 @@ const roleService = {
})
return availIndex > -1
},
selectByName(c, roleName) {
return orm(c).select().from(role).where(eq(role.name, roleName)).get();
}
};

View File

@@ -148,6 +148,7 @@ const settingService = {
noticeWidth: settingRow.noticeWidth,
noticeOffset: settingRow.noticeOffset,
notice: settingRow.notice,
loginDomain: settingRow.loginDomain
};
}
};

View File

@@ -8,7 +8,6 @@ import kvConst from '../const/kv-const';
import KvConst from '../const/kv-const';
import cryptoUtils from '../utils/crypto-utils';
import emailService from './email-service';
import { UAParser } from 'ua-parser-js';
import dayjs from 'dayjs';
import permService from './perm-service';
import roleService from './role-service';
@@ -16,6 +15,7 @@ import emailUtils from '../utils/email-utils';
import saltHashUtils from '../utils/crypto-utils';
import constant from '../const/constant';
import { t } from '../i18n/i18n'
import reqUtils from '../utils/req-utils';
const userService = {
@@ -216,49 +216,22 @@ const userService = {
async updateUserInfo(c, userId, recordCreateIp = false) {
const ua = c.req.header('user-agent') || '';
console.log(ua);
const parser = new UAParser(ua);
const { browser, device, os } = parser.getResult();
let browserInfo = null;
let osInfo = null;
if (browser.name) {
browserInfo = browser.name + ' ' + browser.version;
}
const activeIp = reqUtils.getIp(c);
if (os.name) {
osInfo = os.name + os.version;
}
let deviceInfo = 'Desktop';
const hasVendor = !!device?.vendor;
const hasModel = !!device?.model;
if (hasVendor || hasModel) {
const vendor = device.vendor || '';
const model = device.model || '';
const type = device.type || '';
const namePart = [vendor, model].filter(Boolean).join(' ');
const typePart = type ? ` (${type})` : '';
deviceInfo = (namePart + typePart).trim();
}
const userIp = c.req.header('cf-connecting-ip') || '';
const {os, browser, device} = reqUtils.getUserAgent(c);
const params = {
os: osInfo,
browser: browserInfo,
device: deviceInfo,
activeIp: userIp,
os,
browser,
device,
activeIp,
activeTime: dayjs().format('YYYY-MM-DD HH:mm:ss')
};
if (recordCreateIp) {
params.createIp = userIp;
params.createIp = activeIp;
}
await orm(c)

View File

@@ -2,13 +2,13 @@ import orm from '../entity/orm';
import verifyRecord from '../entity/verify-record';
import { eq, sql, and } from 'drizzle-orm';
import dayjs from 'dayjs';
import ipUtils from '../utils/ip-utils';
import reqUtils from '../utils/req-utils';
import { verifyRecordType } from '../const/entity-const';
const verifyRecordService = {
async selectListByIP(c) {
const ip = ipUtils.getIp(c)
const ip = reqUtils.getIp(c)
return orm(c).select().from(verifyRecord).where(eq(verifyRecord.ip, ip)).all();
},
@@ -18,7 +18,7 @@ const verifyRecordService = {
async isOpenRegVerify(c, regVerifyCount) {
const ip = ipUtils.getIp(c)
const ip = reqUtils.getIp(c)
const row = await orm(c).select().from(verifyRecord).where(and(eq(verifyRecord.ip, ip),eq(verifyRecord.type,verifyRecordType.REG))).get();
@@ -35,7 +35,7 @@ const verifyRecordService = {
async isOpenAddVerify(c, addVerifyCount) {
const ip = ipUtils.getIp(c)
const ip = reqUtils.getIp(c)
const row = await orm(c).select().from(verifyRecord).where(and(eq(verifyRecord.ip, ip),eq(verifyRecord.type,verifyRecordType.ADD))).get();
@@ -53,7 +53,7 @@ const verifyRecordService = {
async increaseRegCount(c) {
const ip = ipUtils.getIp(c)
const ip = reqUtils.getIp(c)
const row = await orm(c).select().from(verifyRecord).where(and(eq(verifyRecord.ip, ip),eq(verifyRecord.type,verifyRecordType.REG))).get();
const now = dayjs().format('YYYY-MM-DD HH:mm:ss');
@@ -70,7 +70,7 @@ const verifyRecordService = {
async increaseAddCount(c) {
const ip = ipUtils.getIp(c)
const ip = reqUtils.getIp(c)
const row = await orm(c).select().from(verifyRecord).where(and(eq(verifyRecord.ip, ip),eq(verifyRecord.type,verifyRecordType.ADD))).get();
const now = dayjs().format('YYYY-MM-DD HH:mm:ss');