mirror of
https://github.com/LingChair/LingChair-V0.git
synced 2025-12-08 01:55:50 +08:00
218 lines
7.3 KiB
JavaScript
218 lines
7.3 KiB
JavaScript
/*
|
|
* ©2024 满月叶
|
|
* Github: MoonLeeeaf
|
|
* 用户辅助类
|
|
*/
|
|
|
|
const io = require("./iolib")
|
|
const hash = require("./hashlib")
|
|
const vals = require("./val")
|
|
|
|
// 获取用户资料所在的路径
|
|
let getUserPath = (name) => {
|
|
return vals.LINGCHAIR_DATA_DIR + "/users/" + name
|
|
}
|
|
|
|
// 用户是否存在
|
|
let isUserExists = (name) => {
|
|
return io.exists(getUserPath(name))
|
|
}
|
|
|
|
let apis = {
|
|
isUserExists: isUserExists,
|
|
|
|
// ================================
|
|
// 无需令牌的 API
|
|
// ================================
|
|
|
|
// 创建账号: 账号, 密码 返回账号唯一 ID 和成功信息 失败返回 null 和原因
|
|
// 账号文件结构: {uid: 10000, name: "GenShin", nick: "Impact", passwd: "SHA-256 + MD5"}
|
|
// 注意: 密码在客户端也应该经过哈希处理(SHA256 + MD5)
|
|
// @APi
|
|
signUp(name, passwd) {
|
|
if (passwd == null || name == null)
|
|
return { msg: "必须输入 账号和密码", code: -1 }
|
|
|
|
let path = getUserPath(name)
|
|
if (isUserExists(name))
|
|
return { msg: "用户账号名重复", code: -1 }
|
|
|
|
io.mkdirs(path)
|
|
|
|
let idCount = io.open(vals.LINGCHAIR_USERS_COUNT_FILE)
|
|
let uid = parseInt(idCount.read("*a"))
|
|
idCount.write((uid + 1) + "").close()
|
|
|
|
io.open(path + "/user.json").writeJson({
|
|
uid: uid,
|
|
name: name,
|
|
nick: null,
|
|
passwd: hash.sha256(passwd) + hash.md5(passwd),
|
|
}).close()
|
|
|
|
return { uid: uid, msg: "成功", code: 0 }
|
|
},
|
|
|
|
// 登录账号: 账号, 密码 返回刷新令牌 失败返回 null 和原因
|
|
// 注意: 密码在客户端应该经过哈希处理(SHA256 + MD5)
|
|
// @API
|
|
signIn(name, passwd) {
|
|
if (passwd == null || name == null)
|
|
return { msg: "必须输入 账号和密码", code: -1 }
|
|
|
|
if (!isUserExists(name))
|
|
return { msg: "用户不存在", code: -1 }
|
|
|
|
if (apis.getPassWordHashedRaw(name) !== (hash.sha256(passwd) + hash.md5(passwd)))
|
|
return { msg: "账号所对应的密码错误", code: -1 }
|
|
|
|
return { msg: "成功", code: 0, refreshToken: apis.getRefreshToken(name, apis.getPassWordHashed(name)) }
|
|
},
|
|
|
|
// 获取刷新令牌: 账号,密码 返回刷新令牌
|
|
// 注意: 密码在客户端也应该经过哈希处理(SHA256 + MD5)
|
|
// 刷新令牌算法: 哈希(用户ID + 当前年 + 当前月 + 密码 + 盐)
|
|
// 有效期: 一个月
|
|
getRefreshToken(name, passwd) {
|
|
let d = new Date()
|
|
let raw = name + d.getFullYear() + d.getMonth() + passwd + "LINGCHAIR-TEST-DEMO"
|
|
return hash.sha256(raw) + hash.md5(raw)
|
|
},
|
|
|
|
// 获取访问令牌: 账号,刷新令牌 返回访问令牌
|
|
// 注意: 密码在客户端也应该经过哈希处理(SHA256 + MD5)
|
|
// 刷新令牌算法: 哈希(用户ID + 当前年 + 当前月 + 密码 + 盐)
|
|
// 有效期: 一天
|
|
getAccessTokenNonApi(name, rt) {
|
|
if (!apis.checkRefreshToken(name, rt))
|
|
return null
|
|
let date = new Date().toLocaleDateString('en-US', { weekday: 'long', year: 'numeric', month: 'numeric', day: 'numeric' })
|
|
return hash.sha256(name + date) + hash.md5(rt + date + "LINGCHAIR-ACCESS-TEST-DEMO")
|
|
},
|
|
|
|
// 获取密码(已被哈希处理) 返回密码
|
|
// 在密码被设置前已经被哈希过,不需要重复
|
|
// 算法: (SHA256 + MD5)
|
|
// 警告: 这是经过二次哈希的
|
|
getPassWordHashed(name) {
|
|
return hash.sha256(apis.getPassWordHashedRaw(name)) + hash.md5(apis.getPassWordHashedRaw(name))
|
|
},
|
|
|
|
// 请勿与上面的混淆
|
|
// 上面的是经过第二次哈希的
|
|
getPassWordHashedRaw(name) {
|
|
return io.open(getUserPath(name) + "/user.json").readJson().passwd
|
|
},
|
|
|
|
// 检测刷新令牌是否正确: 账号, 刷新令牌 返回布尔值
|
|
// 密码在服务端经过哈希保存 不需要重复输入密码
|
|
checkRefreshToken(name, rt) {
|
|
return apis.getRefreshToken(name, apis.getPassWordHashed(name)) === rt
|
|
},
|
|
|
|
// 检测访问令牌是否正确: 账号, 访问令牌 返回布尔值
|
|
// 密码在服务端经过哈希保存 不需要重复输入密码
|
|
checkAccessToken(name, at) {
|
|
return apis.getAccessTokenNonApi(name, apis.getRefreshToken(name, apis.getPassWordHashed(name /* 就是你这个傻逼害得我找两年BUG */))) === at
|
|
},
|
|
|
|
// ================================
|
|
// 需要令牌的 API
|
|
// ================================
|
|
|
|
// 获取访问令牌: 账号, 刷新令牌 返回访问令牌 失败返回 -1 和原因
|
|
// 有效期: 一天
|
|
// 算法: SHA256(name) + MD5(rt + 盐)
|
|
// @Api
|
|
getAccessToken(name, rt) {
|
|
if (!apis.checkRefreshToken(name, rt))
|
|
return { msg: "刷新令牌不正确!", code: -1 }
|
|
|
|
return { msg: "成功", code: 0, accessToken: apis.getAccessTokenNonApi(name, rt) }
|
|
},
|
|
|
|
// 设置头像: 账号, 访问令牌, 头像数据 返回结果
|
|
// @API
|
|
setHeadImage(name, at, head) {
|
|
if (!apis.checkAccessToken(name, at))
|
|
return { msg: "访问令牌不正确!", code: -1 }
|
|
|
|
io.open(vals.LINGCHAIR_USERS_HEAD_DIR + "/" + name + ".png", "w").write(head).close()
|
|
|
|
return { msg: "成功", code: 0 }
|
|
},
|
|
|
|
// 修改昵称
|
|
// @APi
|
|
setNick(name, at, nick) {
|
|
if (!apis.checkAccessToken(name, at))
|
|
return { msg: "访问令牌不正确!", code: -1 }
|
|
|
|
let path = getUserPath(name)
|
|
let configIo = io.open(path + "/user.json", "rw")
|
|
|
|
let config = configIo.readJson()
|
|
config.nick = nick
|
|
configIo.writeJson(config)
|
|
|
|
configIo.close()
|
|
|
|
return { msg: "成功", code: 0 }
|
|
},
|
|
|
|
// 取联系人列表(好友): 账号 返回好友列表
|
|
getFriendsNonApi(name) {
|
|
let file = getUserPath(name) + "/friends.json"
|
|
if (!io.exists(file))
|
|
io.open(file, "w").writeJson({list: [name]}).close()
|
|
|
|
return io.open(file, "r").readJson().list
|
|
},
|
|
|
|
// 加好友: 账号, 欲添加对象
|
|
addFriendNonApi(name, target) {
|
|
let file = getUserPath(name) + "/friends.json"
|
|
if (!io.exists(file))
|
|
io.open(file, "w").writeJson({list: [name]}).close()
|
|
|
|
let friends = io.open(file, "r").readJson()
|
|
friends.list.push(target)
|
|
io.open(file, "r").writeJson(friends).close()
|
|
},
|
|
|
|
// 取用户昵称: 账号 返回昵称
|
|
getNickNonApi(name) {
|
|
let file = getUserPath(name) + "/user.json"
|
|
|
|
return io.open(file, "r").readJson().nick
|
|
},
|
|
|
|
// 取昵称: 账号 返回昵称
|
|
// @API
|
|
getNick(name, at) {
|
|
return { msg: "成功", code: 0, nick: apis.getNickNonApi(name)}
|
|
},
|
|
|
|
// 取联系人列表(好友): 账号, 访问令牌 返回好友列表
|
|
// @API
|
|
getFriends(name, at) {
|
|
if (!apis.checkAccessToken(name, at))
|
|
return { msg: "访问令牌不正确!", code: -1 }
|
|
|
|
return { msg: "成功", code: 0, friends: apis.getFriendsNonApi(name, at)}
|
|
},
|
|
|
|
// 加到好友列表: 账号, 欲加的好友, 访问令牌
|
|
// @API
|
|
addFriend(name, target, at) {
|
|
if (!apis.checkAccessToken(name, at))
|
|
return { msg: "访问令牌不正确!", code: -1 }
|
|
|
|
apis.addFriendNonApi(name, target, at)
|
|
|
|
return { msg: "成功", code: 0 }
|
|
},
|
|
}
|
|
|
|
module.exports = apis
|