Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

clan create, update and delete + flash changes #522

Merged
merged 1 commit into from
Dec 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
11 changes: 11 additions & 0 deletions public/styles/site/clans.sass
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,14 @@
tbody
td
text-align: left

.clanManagement textarea
margin: 1em 1em 2px 1em
background-color: #3f3f3f
color: #ffffff
font-size: var(--paragraph-font-size)
border: 0.5em solid #262626
border-radius: 10px
z-index: 2
position: relative

14 changes: 12 additions & 2 deletions src/backend/AppKernel.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,18 @@ class AppKernel {
})

this.expressApp.use(flash())
this.expressApp.use((req, res, next) => {
res.locals.message = req.flash()
this.expressApp.use(function (req, res, next) {
req.asyncFlash = async function () {
const result = req.flash(...arguments)
await new Promise(resolve => req.session.save(resolve))

return result
}

return next()
})
this.expressApp.use(async (req, res, next) => {
res.locals.connectFlash = () => req.flash()
next()
})

Expand Down
19 changes: 19 additions & 0 deletions src/backend/dependency-injection/RequestContainer.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
const { ContainerBuilder, Reference } = require('node-dependency-injection')
const { UserRepository } = require('../services/UserRepository')
const { UserService } = require('../services/UserService')
const { ClanManagementService } = require('../services/ClanManagementService')
const { ClanManagementRepository } = require('../services/ClanManagementRepository')

module.exports.RequestContainer = (appContainer, request) => {
const container = new ContainerBuilder()
Expand All @@ -11,9 +13,26 @@ module.exports.RequestContainer = (appContainer, request) => {
.addArgument(new Reference('JavaApiClient'))
.lazy = true

container.register('ClanManagementService', ClanManagementService)
.addArgument(new Reference('UserService'))
.addArgument(new Reference('ClanManagementRepository'))
.lazy = true

container.register('ClanManagementRepository', ClanManagementRepository)
.addArgument(new Reference('JavaApiClient'))
.lazy = true

container.register('ClanManagementService', ClanManagementService)
.addArgument(new Reference('UserService'))
.addArgument(new Reference('ClanManagementRepository'))
.addArgument(appContainer.get('ClanService'))
.lazy = true

container.register('JavaApiClient')
.synthetic = true

container.register('UserService', UserService)
.lazy = true

return container
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class RequestContainerCompilerPass {
if (this.request.user) {
container.get('UserService').setUserFromRequest(this.request)
container.set('JavaApiClient', JavaApiClientFactory.createInstance(container.get('UserService'), this.appConfig.apiUrl, this.request.user.oAuthPassport, this.appConfig.oauth.strategy))
container.get('UserService').setUserRepository(container.get('UserRepository'))
}

return container
Expand Down
8 changes: 8 additions & 0 deletions src/backend/routes/views/clanRouter.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
const create = require('../views/clans/create')
const express = require('../../ExpressApp')
const router = express.Router()
const middlewares = require('../middleware')

// This will be replaced soon, therefor I did not spend time on it
router.get('/', (req, res) => res.render('clans/clans'))
Expand All @@ -12,6 +14,12 @@ router.get('/view/:id', async (req, res) => {
return res.render('clans/clan', { clan: await req.appContainer.get('ClanService').getClan(clanId) })
})

router.get('/create', create)
router.post('/create', create)
router.get('/manage', middlewares.isAuthenticated(), require('./clans/get/manage'))
router.post('/update', middlewares.isAuthenticated(), require('./clans/post/update'))
router.post('/destroy', middlewares.isAuthenticated(), require('./clans/post/destroy'))

router.get('*', (req, res) => res.status(503).render('errors/503-known-issue'))

module.exports = router
64 changes: 64 additions & 0 deletions src/backend/routes/views/clans/create.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
const { body, validationResult, matchedData } = require('express-validator')
const { JavaApiError } = require('../../../services/ApiErrors')

module.exports =
[
body('clan_tag', 'Please indicate the clan tag - No special characters and 3 characters maximum').notEmpty().isLength({ max: 3 }),
body('clan_description', 'Please add a description for your clan').notEmpty().isLength({ max: 1000 }),
body('clan_name', "Please indicate your clan's name").notEmpty().isLength({ max: 40 }),
async (req, res) => {
if (req.requestContainer.get('UserService').getUser()?.clan) {
return res.redirect('/clans/manage')
}

if (req.method === 'POST') {
const errors = validationResult(req)

if (!errors.isEmpty()) {
return res.render('clans/create', {
errors: {
class: 'alert-danger',
messages: errors,
type: 'Error!'
},
clan_tag: req.body.clan_tag,
clan_name: req.body.clan_name,
clan_description: req.body.clan_description
})
}

try {
const data = matchedData(req)
await req.requestContainer.get('ClanManagementService').create(data.clan_tag, data.clan_name, data.clan_description)

await req.asyncFlash('info', 'Clan created')

return res.redirect('/clans/view/' + req.requestContainer.get('UserService').getUser().clan.id)
} catch (e) {
let messages = { errors: [{ msg: 'Server-Error while creating the clan' }] }

console.error(e.stack)
if (e instanceof JavaApiError && e.error.errors[0]) {
messages = { errors: [{ msg: e.error.errors[0].detail }] }
}

return res.render('clans/create', {
clan_tag: req.body.clan_tag,
clan_name: req.body.clan_name,
clan_description: req.body.clan_description,
errors: {
class: 'alert-danger',
messages,
type: 'Error!'
}
})
}
}

res.render('clans/create', {
clan_tag: '',
clan_name: '',
clan_description: ''
})
}
]
53 changes: 0 additions & 53 deletions src/backend/routes/views/clans/get/create.js

This file was deleted.

139 changes: 16 additions & 123 deletions src/backend/routes/views/clans/get/manage.js
Original file line number Diff line number Diff line change
@@ -1,129 +1,22 @@
const request = require('request')

exports = module.exports = function (req, res) {
const locals = res.locals

// locals.section is used to set the currently selected
// item in the header navigation.
locals.section = 'clan'

let flash = null

let clanMembershipId = null
try {
clanMembershipId = req.user.data.attributes.clan.membershipId
} catch {
// The user doesnt belong to a clan
res.redirect('/clans')
return
const { JavaApiError } = require('../../../../services/ApiErrors')
exports = module.exports = async (req, res) => {
const clanMembershipId = req.requestContainer.get('UserService').getUser()?.clan?.membershipId || null
if (!clanMembershipId) {
return res.redirect('/clans')
}

// In case the user has just generated an invite link
if (req.query.invitation_id) {
flash = {}
flash.class = 'alert-invite'

flash.messages = [
{
msg:
`<p><a id='inviteLink' onclick='return false' href='${process.env.HOST}/clans/accept_invite?i=${req.query.invitation_id}'> Right click on me and copy the invitation link</a></p>Note: It only works for the user you typed.`
}
]
flash.type = ''
}

request.get(
{
url:
process.env.API_URL +
'/data/clanMembership/' + clanMembershipId + '/clan' +
'?include=memberships.player' +
'&fields[clan]=createTime,description,name,tag,updateTime,websiteUrl,founder,leader' +
'&fields[player]=login,updateTime' +
'&fields[clanMembership]=createTime,player',
headers: {
Authorization: 'Bearer ' + req.user.data.attributes.token
}
},
function (err, childRes, body) {
const clan = JSON.parse(body)

if (err || !clan.data) {
flash = {}
flash.class = 'alert-danger'
flash.messages = [{ msg: 'Unknown error while retrieving your clan information' }]
flash.type = 'Error!'

const buff = Buffer.from(JSON.stringify(flash))
const data = buff.toString('base64')

return res.redirect('/clans?flash=' + data)
}

if (clan.data.relationships.leader.data.id !== req.user.data.id) {
// Not the leader! Shouldn't be able to manage stuff
res.redirect(`/clans/${req.user.data.attributes.clan.tag}?member=true`)
return
}

locals.clan_name = clan.data.attributes.name
locals.clan_tag = clan.data.attributes.tag
locals.clan_description = clan.data.attributes.description
locals.clan_create_time = clan.data.attributes.createTime
locals.me = req.user.data.id
locals.clan_id = clan.data.id
locals.clan_link = process.env.HOST + '/clans/see?id=' + clan.data.id

const members = {}
let player = null
let membership = null
let member = null

for (const k in clan.included) {
switch (clan.included[k].type) {
case 'player':
player = clan.included[k]
if (!members[player.id]) members[player.id] = {}
members[player.id].id = player.id
members[player.id].name = player.attributes.login

if (clan.data.relationships.founder.data.id === player.id) {
locals.founder_name = player.attributes.login
}
break

case 'clanMembership':
membership = clan.included[k]
member = membership.relationships.player.data
if (!members[member.id]) members[member.id] = {}
members[member.id].id = member.id
members[member.id].membershipId = membership.id
members[member.id].joinedAt = membership.attributes.createTime
break
}
}
try {
const clan = await req.appContainer.get('ClanService').getClanMembership(clanMembershipId)

locals.clan_members = members
return res.render('clans/manage', { clan_description: clan.clan_description, clan_name: clan.clan_name, clan_tag: clan.clan_tag })
} catch (e) {
let message = e.toString()
if (e instanceof JavaApiError && e.error?.errors) {
message = e.error.errors[0].detail
}

if (req.originalUrl === '/clan_created') {
flash = {}
flash.class = 'alert-success'
flash.messages = [{ msg: 'You have successfully created your clan' }]
flash.type = 'Success!'
} else if (req.query.flash) {
const buff = Buffer.from(req.query.flash, 'base64')
const text = buff.toString('ascii')
try {
flash = JSON.parse(text)
} catch (e) {
console.error('Parsing error while trying to decode a flash error: ' + text)
console.error(e)
flash = [{ msg: 'Unknown error' }]
}
}
await req.asyncFlash('error', message)

// Render the view
res.render('clans/manage', { flash })
}
)
return res.redirect('/')
}
}