mirror of
https://github.com/johndoe6345789/metabuilder.git
synced 2026-04-25 22:34:56 +00:00
339 lines
8.8 KiB
Lua
339 lines
8.8 KiB
Lua
-- user_manager/seed/scripts/db/operations.lua
|
|
-- DBAL operations for User management
|
|
-- Uses existing User entity from Prisma schema
|
|
-- @module user_manager.db.operations
|
|
|
|
local M = {}
|
|
local json = require('json')
|
|
|
|
---------------------------------------------------------------------------
|
|
-- USER CRUD OPERATIONS
|
|
---------------------------------------------------------------------------
|
|
|
|
---@class UserCreateParams
|
|
---@field tenantId string
|
|
---@field email string
|
|
---@field username string
|
|
---@field password string Hashed password
|
|
---@field displayName string|nil
|
|
---@field avatar string|nil
|
|
---@field level number 0-6 permission level
|
|
---@field status string active|inactive|banned
|
|
|
|
---Create a new user
|
|
---@param dbal table DBAL client instance
|
|
---@param params UserCreateParams
|
|
---@return table Created user
|
|
function M.createUser(dbal, params)
|
|
return dbal:create('User', {
|
|
tenantId = params.tenantId,
|
|
email = params.email,
|
|
username = params.username,
|
|
password = params.password,
|
|
displayName = params.displayName or params.username,
|
|
avatar = params.avatar,
|
|
level = params.level or 1,
|
|
status = params.status or 'active',
|
|
createdAt = os.time() * 1000,
|
|
updatedAt = os.time() * 1000,
|
|
})
|
|
end
|
|
|
|
---Get user by ID
|
|
---@param dbal table
|
|
---@param userId string
|
|
---@return table|nil User
|
|
function M.getUser(dbal, userId)
|
|
return dbal:read('User', userId)
|
|
end
|
|
|
|
---Get user by email
|
|
---@param dbal table
|
|
---@param tenantId string
|
|
---@param email string
|
|
---@return table|nil User
|
|
function M.getUserByEmail(dbal, tenantId, email)
|
|
return dbal:findFirst('User', {
|
|
where = { tenantId = tenantId, email = email },
|
|
})
|
|
end
|
|
|
|
---Get user by username
|
|
---@param dbal table
|
|
---@param tenantId string
|
|
---@param username string
|
|
---@return table|nil User
|
|
function M.getUserByUsername(dbal, tenantId, username)
|
|
return dbal:findFirst('User', {
|
|
where = { tenantId = tenantId, username = username },
|
|
})
|
|
end
|
|
|
|
---List users
|
|
---@param dbal table
|
|
---@param tenantId string
|
|
---@param status string|nil Filter by status
|
|
---@param minLevel number|nil Minimum permission level
|
|
---@param take number|nil
|
|
---@param skip number|nil
|
|
---@return table List result
|
|
function M.listUsers(dbal, tenantId, status, minLevel, take, skip)
|
|
local where = { tenantId = tenantId }
|
|
|
|
if status then
|
|
where.status = status
|
|
end
|
|
|
|
local result = dbal:list('User', {
|
|
where = where,
|
|
orderBy = { createdAt = 'desc' },
|
|
take = take or 50,
|
|
skip = skip or 0,
|
|
})
|
|
|
|
-- Filter by minLevel if specified
|
|
if minLevel and result.items then
|
|
local filtered = {}
|
|
for _, user in ipairs(result.items) do
|
|
if (user.level or 0) >= minLevel then
|
|
table.insert(filtered, user)
|
|
end
|
|
end
|
|
result.items = filtered
|
|
end
|
|
|
|
return result
|
|
end
|
|
|
|
---Update user
|
|
---@param dbal table
|
|
---@param userId string
|
|
---@param updates table
|
|
---@return table Updated user
|
|
function M.updateUser(dbal, userId, updates)
|
|
updates.updatedAt = os.time() * 1000
|
|
return dbal:update('User', userId, updates)
|
|
end
|
|
|
|
---Update user profile
|
|
---@param dbal table
|
|
---@param userId string
|
|
---@param displayName string|nil
|
|
---@param avatar string|nil
|
|
---@param bio string|nil
|
|
---@return table Updated user
|
|
function M.updateProfile(dbal, userId, displayName, avatar, bio)
|
|
local updates = { updatedAt = os.time() * 1000 }
|
|
|
|
if displayName ~= nil then
|
|
updates.displayName = displayName
|
|
end
|
|
if avatar ~= nil then
|
|
updates.avatar = avatar
|
|
end
|
|
if bio ~= nil then
|
|
updates.bio = bio
|
|
end
|
|
|
|
return dbal:update('User', userId, updates)
|
|
end
|
|
|
|
---Change user password
|
|
---@param dbal table
|
|
---@param userId string
|
|
---@param hashedPassword string
|
|
---@return table Updated user
|
|
function M.changePassword(dbal, userId, hashedPassword)
|
|
return M.updateUser(dbal, userId, {
|
|
password = hashedPassword,
|
|
})
|
|
end
|
|
|
|
---Set user status
|
|
---@param dbal table
|
|
---@param userId string
|
|
---@param status string active|inactive|banned
|
|
---@return table Updated user
|
|
function M.setStatus(dbal, userId, status)
|
|
return M.updateUser(dbal, userId, { status = status })
|
|
end
|
|
|
|
---Activate user
|
|
---@param dbal table
|
|
---@param userId string
|
|
function M.activateUser(dbal, userId)
|
|
return M.setStatus(dbal, userId, 'active')
|
|
end
|
|
|
|
---Deactivate user
|
|
---@param dbal table
|
|
---@param userId string
|
|
function M.deactivateUser(dbal, userId)
|
|
return M.setStatus(dbal, userId, 'inactive')
|
|
end
|
|
|
|
---Ban user
|
|
---@param dbal table
|
|
---@param userId string
|
|
---@param reason string|nil
|
|
function M.banUser(dbal, userId, reason)
|
|
return M.updateUser(dbal, userId, {
|
|
status = 'banned',
|
|
banReason = reason,
|
|
bannedAt = os.time() * 1000,
|
|
})
|
|
end
|
|
|
|
---Unban user
|
|
---@param dbal table
|
|
---@param userId string
|
|
function M.unbanUser(dbal, userId)
|
|
return M.updateUser(dbal, userId, {
|
|
status = 'active',
|
|
banReason = nil,
|
|
bannedAt = nil,
|
|
})
|
|
end
|
|
|
|
---------------------------------------------------------------------------
|
|
-- PERMISSION OPERATIONS
|
|
---------------------------------------------------------------------------
|
|
|
|
---Set user permission level
|
|
---@param dbal table
|
|
---@param userId string
|
|
---@param level number 0-6
|
|
---@return table Updated user
|
|
function M.setLevel(dbal, userId, level)
|
|
if level < 0 or level > 6 then
|
|
error('Invalid permission level: ' .. tostring(level))
|
|
end
|
|
return M.updateUser(dbal, userId, { level = level })
|
|
end
|
|
|
|
---Promote user by one level
|
|
---@param dbal table
|
|
---@param userId string
|
|
---@param maxLevel number|nil Maximum level to promote to
|
|
---@return table Updated user
|
|
function M.promoteUser(dbal, userId, maxLevel)
|
|
local user = M.getUser(dbal, userId)
|
|
if not user then
|
|
error('User not found: ' .. userId)
|
|
end
|
|
|
|
local newLevel = math.min((user.level or 0) + 1, maxLevel or 6)
|
|
return M.setLevel(dbal, userId, newLevel)
|
|
end
|
|
|
|
---Demote user by one level
|
|
---@param dbal table
|
|
---@param userId string
|
|
---@return table Updated user
|
|
function M.demoteUser(dbal, userId)
|
|
local user = M.getUser(dbal, userId)
|
|
if not user then
|
|
error('User not found: ' .. userId)
|
|
end
|
|
|
|
local newLevel = math.max((user.level or 0) - 1, 0)
|
|
return M.setLevel(dbal, userId, newLevel)
|
|
end
|
|
|
|
---Check if user has minimum permission level
|
|
---@param dbal table
|
|
---@param userId string
|
|
---@param requiredLevel number
|
|
---@return boolean
|
|
function M.hasPermission(dbal, userId, requiredLevel)
|
|
local user = M.getUser(dbal, userId)
|
|
if not user then
|
|
return false
|
|
end
|
|
return (user.level or 0) >= requiredLevel
|
|
end
|
|
|
|
---------------------------------------------------------------------------
|
|
-- BULK OPERATIONS
|
|
---------------------------------------------------------------------------
|
|
|
|
---List admins (level >= 3)
|
|
---@param dbal table
|
|
---@param tenantId string
|
|
---@return table[] Admin users
|
|
function M.listAdmins(dbal, tenantId)
|
|
local result = M.listUsers(dbal, tenantId, 'active', 3, 100, 0)
|
|
return result.items or {}
|
|
end
|
|
|
|
---List moderators (level >= 2)
|
|
---@param dbal table
|
|
---@param tenantId string
|
|
---@return table[] Moderator users
|
|
function M.listModerators(dbal, tenantId)
|
|
local result = M.listUsers(dbal, tenantId, 'active', 2, 100, 0)
|
|
return result.items or {}
|
|
end
|
|
|
|
---Count users by status
|
|
---@param dbal table
|
|
---@param tenantId string
|
|
---@return table Counts by status
|
|
function M.countByStatus(dbal, tenantId)
|
|
local all = M.listUsers(dbal, tenantId, nil, nil, 10000, 0)
|
|
|
|
local counts = {
|
|
active = 0,
|
|
inactive = 0,
|
|
banned = 0,
|
|
total = 0,
|
|
}
|
|
|
|
for _, user in ipairs(all.items or {}) do
|
|
counts.total = counts.total + 1
|
|
local status = user.status or 'active'
|
|
counts[status] = (counts[status] or 0) + 1
|
|
end
|
|
|
|
return counts
|
|
end
|
|
|
|
---Search users by username or email
|
|
---@param dbal table
|
|
---@param tenantId string
|
|
---@param query string
|
|
---@param take number|nil
|
|
---@return table[] Matching users
|
|
function M.searchUsers(dbal, tenantId, query, take)
|
|
local all = M.listUsers(dbal, tenantId, nil, nil, 1000, 0)
|
|
local matches = {}
|
|
local lowerQuery = query:lower()
|
|
|
|
for _, user in ipairs(all.items or {}) do
|
|
local username = (user.username or ''):lower()
|
|
local email = (user.email or ''):lower()
|
|
local displayName = (user.displayName or ''):lower()
|
|
|
|
if username:find(lowerQuery, 1, true) or
|
|
email:find(lowerQuery, 1, true) or
|
|
displayName:find(lowerQuery, 1, true) then
|
|
table.insert(matches, user)
|
|
if #matches >= (take or 20) then
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
return matches
|
|
end
|
|
|
|
---Delete user
|
|
---@param dbal table
|
|
---@param userId string
|
|
---@return boolean Success
|
|
function M.deleteUser(dbal, userId)
|
|
return dbal:delete('User', userId)
|
|
end
|
|
|
|
return M
|