Skip to content

Commit

Permalink
Merge pull request #247 from developmentseed/feature/badges
Browse files Browse the repository at this point in the history
Add badges routes
  • Loading branch information
vgeorge authored Mar 14, 2022
2 parents 1b87113 + 9d82c27 commit cc2fa4e
Show file tree
Hide file tree
Showing 16 changed files with 927 additions and 64 deletions.
16 changes: 16 additions & 0 deletions app/db/migrations/20220222155039_add_badges.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
exports.up = async function (knex) {
await knex.schema.createTable('organization_badge', (table) => {
table.increments('id')
table
.integer('organization_id')
.references('id')
.inTable('organization')
.onDelete('CASCADE')
table.string('name').notNullable()
table.string('color').notNullable()
})
}

exports.down = async function (knex) {
await knex.schema.dropTable('organization_badge')
}
20 changes: 20 additions & 0 deletions app/db/migrations/20220302104250_add_user_badges.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
exports.up = async function (knex) {
await knex.schema.createTable('user_badge', (table) => {
table
.integer('badge_id')
.references('id')
.inTable('organization_badge')
.onDelete('CASCADE')
table
.integer('user_id')
.references('id')
.inTable('organization_badge')
.onDelete('CASCADE')
table.datetime('assigned_at').defaultTo(knex.fn.now())
table.datetime('valid_until')
})
}

exports.down = async function (knex) {
await knex.schema.dropTable('user_badge')
}
22 changes: 21 additions & 1 deletion app/lib/profile.js
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,25 @@ async function getUserManageToken (id) {
return unpack(conn('users').select('manageToken').where('id', id).debug())
}

async function getUserBadges (id) {
const conn = await db()
return conn('user_badge')
.select([
'id',
'assigned_at',
'valid_until',
'organization_id',
'name',
'color'
])
.leftJoin(
'organization_badge',
'user_badge.badge_id',
'organization_badge.id'
)
.where('user_badge.user_id', id)
}

module.exports = {
addProfileKeys,
modifyProfileKey,
Expand All @@ -263,5 +282,6 @@ module.exports = {
setProfile,
getProfile,
getTableForProfileType,
getUserManageToken
getUserManageToken,
getUserBadges
}
269 changes: 269 additions & 0 deletions app/manage/badges.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,269 @@
const db = require('../db')
const yup = require('yup')
const organization = require('../lib/organization')
const profile = require('../lib/profile')
const { routeWrapper } = require('./utils')

/**
* Get the list of badges of an organization
*/
const listBadges = routeWrapper({
validate: {
params: yup
.object({
id: yup.number().required().positive().integer()
})
.required()
},
handler: async function (req, reply) {
try {
const conn = await db()
const badges = await conn('organization_badge')
.select('*')
.where('organization_id', req.params.id)
reply.send(badges)
} catch (err) {
console.log(err)
return reply.boom.badRequest(err.message)
}
}
})

/**
* Create organization badge
*/
const createBadge = routeWrapper({
validate: {
params: yup
.object({
id: yup.number().required().positive().integer()
})
.required(),
body: yup
.object({
name: yup.string().required(),
color: yup.string().required()
})
.required()
},
handler: async function (req, reply) {
try {
const conn = await db()
const [badge] = await conn('organization_badge')
.insert({
organization_id: req.params.id,
...req.body
})
.returning('*')
reply.send(badge)
} catch (err) {
console.log(err)
return reply.boom.badRequest(err.message)
}
}
})

/**
* Edit organization badge
*/
const patchBadge = routeWrapper({
validate: {
params: yup
.object({
id: yup.number().required().positive().integer(),
badgeId: yup.number().required().positive().integer()
})
.required(),
body: yup
.object({
name: yup.string().optional(),
color: yup.string().optional()
})
.required()
},
handler: async function (req, reply) {
try {
const conn = await db()
const [badge] = await conn('organization_badge')
.update(req.body)
.where('id', req.params.badgeId)
.returning('*')
reply.send(badge)
} catch (err) {
console.log(err)
return reply.boom.badRequest(err.message)
}
}
})

/**
* Delete organization badge
*/
const deleteBadge = routeWrapper({
validate: {
params: yup
.object({
badgeId: yup.number().required().positive().integer()
})
.required()
},
handler: async function (req, reply) {
try {
const conn = await db()
await conn('organization_badge')
.delete()
.where('id', req.params.badgeId)
return reply.sendStatus(200)
} catch (err) {
console.log(err)
return reply.boom.badRequest(err.message)
}
}
})

/**
* Assign organization badge to an user
*/
const assignUserBadge = routeWrapper({
validate: {
params: yup
.object({
id: yup.number().required().positive().integer(),
badgeId: yup.number().required().positive().integer(),
userId: yup.number().required().positive().integer()
})
.required(),
body: yup
.object({
assigned_at: yup.date().optional(),
valid_until: yup.date().optional()
})
},
handler: async function (req, reply) {
try {
const conn = await db()

// user is member
await organization.isMember(req.params.id, req.params.userId)

// assign badge
const [badge] = await conn('user_badge')
.insert({
user_id: req.params.userId,
badge_id: req.params.badgeId,
assigned_at: req.body.assigned_at,
valid_until: req.body.valid_until
})
.returning('*')

reply.send(badge)
} catch (err) {
console.log(err)
return reply.boom.badRequest(err.message)
}
}
})

/**
* List badges of an user
*/
const listUserBadges = routeWrapper({
validate: {
params: yup
.object({
userId: yup.number().required().positive().integer()
})
.required()
},
handler: async function (req, reply) {
try {
const badges = await profile.getUserBadges(req.params.userId)
reply.send({ badges })
} catch (err) {
console.log(err)
return reply.boom.badRequest(err.message)
}
}
})

/**
* Update a badge assigned to an user
*/
const updateUserBadge = routeWrapper({
validate: {
params: yup
.object({
badgeId: yup.number().required().positive().integer(),
userId: yup.number().required().positive().integer()
})
.required(),
body: yup
.object({
assigned_at: yup.date().optional(),
valid_until: yup.date().optional()
})
},
handler: async function (req, reply) {
try {
const conn = await db()

// assign badge
const [badge] = await conn('user_badge')
.update({
assigned_at: req.body.assigned_at,
valid_until: req.body.valid_until
})
.where({
user_id: req.params.userId,
badge_id: req.params.badgeId
})
.returning('*')

reply.send(badge)
} catch (err) {
console.log(err)
return reply.boom.badRequest(err.message)
}
}
})

/**
* Remove badge assign to an user
*/
const removeUserBadge = routeWrapper({
validate: {
params: yup
.object({
badgeId: yup.number().required().positive().integer(),
userId: yup.number().required().positive().integer()
})
.required()
},
handler: async function (req, reply) {
try {
const conn = await db()

// delete user badge
await conn('user_badge').delete().where({
user_id: req.params.userId,
badge_id: req.params.badgeId
})

reply.sendStatus(200)
} catch (err) {
console.log(err)
return reply.boom.badRequest(err.message)
}
}
})

module.exports = {
listBadges,
createBadge,
patchBadge,
deleteBadge,
assignUserBadge,
listUserBadges,
updateUserBadge,
removeUserBadge
}
Loading

0 comments on commit cc2fa4e

Please sign in to comment.