generated from azures04/Base-REST-API
Add badges, checkins, and transport endpoints
Introduce gamification and check-in support plus expanded transport/admin APIs. Added DDL for checkins, badges and user_badges. New repositories: badgeRepository, userBadgeRepository, checkinRepository. New routes: admin badge management, admin transport (lines/platforms/stations), public transport endpoints, user checkins and stations endpoints, and user badges on /me. Services updated: adminService (badge CRUD & user assignment), userService (checkins, badge queries), authService (hasAdminRights). Minor package.json name update. These changes implement database, repo, service and route wiring for badges, user_badins and checkin features and additional transport admin routes.
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
const { DefaultError } = require("../errors/errors")
|
||||
const banRepo = require("../repositories/banRepo")
|
||||
const badgeRepo = require("../repositories/badgeRepository")
|
||||
const userBadgeRepo = require("../repositories/userBadgeRepository")
|
||||
|
||||
async function banUser(userId, message, expiresAt) {
|
||||
const existingBan = await banRepo.isBanned(userId)
|
||||
@@ -31,8 +33,91 @@ async function isUserBanned(userId) {
|
||||
return true
|
||||
}
|
||||
|
||||
async function createBadge({ name, description, icon, condition }) {
|
||||
const existing = await badgeRepo.findAllBadges()
|
||||
if (existing.some(b => b.name === name)) {
|
||||
throw new DefaultError(409, "Badge already exists", "Duplicate badge name")
|
||||
}
|
||||
return await badgeRepo.createBadge(name, description, icon, condition)
|
||||
}
|
||||
|
||||
async function getAllBadges() {
|
||||
return await badgeRepo.findAllBadges()
|
||||
}
|
||||
|
||||
async function getBadgeById({ badgeId }) {
|
||||
const badge = await badgeRepo.findBadgeById(badgeId)
|
||||
if (!badge) {
|
||||
throw new DefaultError(404, "Badge not found", "Badge ID does not exist")
|
||||
}
|
||||
return badge
|
||||
}
|
||||
|
||||
async function updateBadge({ badgeId, updateData }) {
|
||||
const badge = await badgeRepo.findBadgeById(badgeId)
|
||||
if (!badge) {
|
||||
throw new DefaultError(404, "Badge not found", "Badge ID does not exist")
|
||||
}
|
||||
|
||||
const allowedFields = ["name", "description", "icon", "condition"]
|
||||
const filteredData = Object.keys(updateData)
|
||||
.filter(key => allowedFields.includes(key))
|
||||
.reduce((obj, key) => {
|
||||
obj[key] = updateData[key]
|
||||
return obj
|
||||
}, {})
|
||||
|
||||
if (Object.keys(filteredData).length === 0) {
|
||||
throw new DefaultError(400, "No valid fields to update", "Invalid update data")
|
||||
}
|
||||
|
||||
return await badgeRepo.updateBadge(badgeId, filteredData)
|
||||
}
|
||||
|
||||
async function deleteBadge({ badgeId }) {
|
||||
const badge = await badgeRepo.findBadgeById(badgeId)
|
||||
if (!badge) {
|
||||
throw new DefaultError(404, "Badge not found", "Badge ID does not exist")
|
||||
}
|
||||
return await badgeRepo.deleteBadge(badgeId)
|
||||
}
|
||||
|
||||
async function assignBadgeToUser({ userId, badgeId }) {
|
||||
const badge = await badgeRepo.findBadgeById(badgeId)
|
||||
if (!badge) {
|
||||
throw new DefaultError(404, "Badge not found", "Badge ID does not exist")
|
||||
}
|
||||
|
||||
const hasAlready = await userBadgeRepo.hasBadge(userId, badgeId)
|
||||
if (hasAlready) {
|
||||
throw new DefaultError(409, "User already has this badge", "Duplicate badge assignment")
|
||||
}
|
||||
|
||||
return await userBadgeRepo.assignBadgeToUser(userId, badgeId)
|
||||
}
|
||||
|
||||
async function removeBadgeFromUser({ userId, badgeId }) {
|
||||
const badge = await badgeRepo.findBadgeById(badgeId)
|
||||
if (!badge) {
|
||||
throw new DefaultError(404, "Badge not found", "Badge ID does not exist")
|
||||
}
|
||||
|
||||
const success = await userBadgeRepo.removeBadgeFromUser(userId, badgeId)
|
||||
if (!success) {
|
||||
throw new DefaultError(404, "Badge not assigned to user", "User does not have this badge")
|
||||
}
|
||||
return success
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
banUser,
|
||||
unbanUser,
|
||||
isUserBanned
|
||||
isUserBanned,
|
||||
createBadge,
|
||||
getAllBadges,
|
||||
getBadgeById,
|
||||
updateBadge,
|
||||
deleteBadge,
|
||||
assignBadgeToUser,
|
||||
removeBadgeFromUser
|
||||
}
|
||||
@@ -111,6 +111,13 @@ async function isLogged(req, res, next) {
|
||||
next()
|
||||
}
|
||||
|
||||
function hasAdminRights(req, res, next) {
|
||||
if (req.user?.role == "admin") {
|
||||
return next()
|
||||
}
|
||||
throw new DefaultError(403, "Forbidden", "You must be administrator.")
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
isLogged,
|
||||
loginLocal,
|
||||
@@ -118,5 +125,6 @@ module.exports = {
|
||||
resetPassword,
|
||||
registerLocal,
|
||||
changePassword,
|
||||
hasAdminRights,
|
||||
refreshAccessToken,
|
||||
}
|
||||
+45
-1
@@ -1,4 +1,6 @@
|
||||
const userRepo = require("../repositories/usersRepo")
|
||||
const userBadgeRepo = require("../repositories/userBadgeRepository")
|
||||
const checkinRepo = require("../repositories/checkinRepository")
|
||||
const cache = require("../modules/cache")
|
||||
|
||||
async function getProfile({ userId }) {
|
||||
@@ -30,11 +32,53 @@ async function getShadowUser({ serverId, remoteId }) {
|
||||
return await userRepo.findByServerAndRemoteId(serverId, remoteId)
|
||||
}
|
||||
|
||||
async function getUserBadges({ userId }) {
|
||||
return await userBadgeRepo.findUserBadges(userId)
|
||||
}
|
||||
|
||||
async function countUserBadges({ userId }) {
|
||||
return await userBadgeRepo.countUserBadges(userId)
|
||||
}
|
||||
|
||||
async function hasBadge({ userId, badgeId }) {
|
||||
return await userBadgeRepo.hasBadge(userId, badgeId)
|
||||
}
|
||||
|
||||
async function createCheckin({ userId, stationId, platformId, latitude, longitude, distance }) {
|
||||
const checkinId = await checkinRepo.createCheckin(userId, stationId, platformId, latitude, longitude, distance)
|
||||
cache.users.delete(userId)
|
||||
return checkinId
|
||||
}
|
||||
|
||||
async function getUserCheckins({ userId, limit = 50, offset = 0 }) {
|
||||
return await checkinRepo.findCheckinsByUserId(userId, limit, offset)
|
||||
}
|
||||
|
||||
async function getUserCheckinsCount({ userId }) {
|
||||
return await checkinRepo.countCheckinsByUser(userId)
|
||||
}
|
||||
|
||||
async function getUserUniqueStations({ userId }) {
|
||||
return await checkinRepo.findUniqueStationsByUser(userId)
|
||||
}
|
||||
|
||||
async function getUserStationCheckinsCount({ userId, stationId }) {
|
||||
return await checkinRepo.countCheckinsByUserAndStation(userId, stationId)
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
isLocal,
|
||||
getProfile,
|
||||
createUser,
|
||||
updateProfile,
|
||||
deleteAccount,
|
||||
getShadowUser
|
||||
getShadowUser,
|
||||
getUserBadges,
|
||||
countUserBadges,
|
||||
hasBadge,
|
||||
createCheckin,
|
||||
getUserCheckins,
|
||||
getUserCheckinsCount,
|
||||
getUserUniqueStations,
|
||||
getUserStationCheckinsCount
|
||||
}
|
||||
Reference in New Issue
Block a user