diff --git a/express.js b/express.js
index 310938ff..73599592 100644
--- a/express.js
+++ b/express.js
@@ -102,12 +102,12 @@ app.use("/news", newsRouter)
// --- UNPROTECTED ROUTES ---
const appGetRouteArray = [
// This first '' is the home/index page
- '', 'newshub', 'campaign-missions', 'scfa-vs-faf', 'donation', 'tutorials-guides', 'ai', 'patchnotes', 'faf-teams', 'contribution', 'content-creators', 'tournaments', 'training', 'leaderboards', 'play', 'clans',];
+ '', 'newshub', 'campaign-missions', 'scfa-vs-faf', 'donation', 'tutorials-guides', 'ai', 'patchnotes', 'faf-teams', 'contribution', 'content-creators', 'tournaments', 'training', 'leaderboards', 'play'];
//Renders every page written above
appGetRouteArray.forEach(page => app.get(`/${page}`, (req, res) => {
// disabled due https://github.com/FAForever/website/issues/445
- if (['leaderboards', 'clans'].includes(page)) {
+ if (['leaderboards'].includes(page)) {
return res.status(503).render('errors/503-known-issue')
}
res.render(page);
@@ -150,24 +150,21 @@ const routes = './routes/views/';
const clansRoutesGet = [
'create', 'manage', 'accept_invite',];
-// disabled due https://github.com/FAForever/website/issues/445
-// clansRoutesGet.forEach(page => app.get(`/clans/${page}`, loggedIn, require(`${routes}clans/get/${page}`)));
-clansRoutesGet.forEach(page => app.get(`/clans/${page}`, loggedIn, (req, res) => res.status(503).render('errors/503-known-issue')));
+clansRoutesGet.forEach(page => app.get(`/clans/${page}`, loggedIn, require(`${routes}clans/get/${page}`)));
const clansRoutesPost = [
'create', 'destroy', 'invite', 'kick', 'transfer', 'update', 'leave', 'join',];
-// disabled due https://github.com/FAForever/website/issues/445
-// clansRoutesPost.forEach(page => app.post(`/clans/${page}`, loggedIn, require(`${routes}clans/post/${page}`)));
-clansRoutesPost.forEach(page => app.post(`/clans/${page}`, loggedIn, (req, res) => res.status(503).render('errors/503-known-issue')));
+clansRoutesPost.forEach(page => app.post(`/clans/${page}`, loggedIn, require(`${routes}clans/post/${page}`)));
+app.get('/clans/*', (req, res) => {
+ let id = req.path.slice(-3);
+ res.redirect(`/clans/getClan?tag=${id}`);
+});
-// disabled due https://github.com/FAForever/website/issues/445
+//Unprotected clan routes
+app.get('/clans', require(`${routes}clans/get/clans`));
+app.get('/clans/getClan', require(`${routes}clans/get/getClan`));
//When searching for a specific clan
-// app.get('/clans/*', (req, res) => {
-// res.render(`clans/seeClan`);
-// });
-app.get('/clans/*', (req, res) => res.status(503).render('errors/503-known-issue'));
-
// Markdown Routes
diff --git a/public/js/app/clans.js b/public/js/app/clans.js
index 9ddd1faa..3859ffcb 100644
--- a/public/js/app/clans.js
+++ b/public/js/app/clans.js
@@ -47,7 +47,6 @@ function clanUpdate() {
for (clanIndex; clanIndex < next100Players; clanIndex++) {
if (clanIndex < 0) {
clanIndex = 0;
- console.log('There are no more players left.');
}
// Gets the player data and inserts it into the li element
diff --git a/public/js/app/getClans.js b/public/js/app/getClans.js
deleted file mode 100644
index f34fec5e..00000000
--- a/public/js/app/getClans.js
+++ /dev/null
@@ -1,72 +0,0 @@
-const clanName = document.getElementById('clanName');
-const clanTag = document.getElementById('clanTag');
-const clanDescription = document.getElementById('clanDescription');
-const clanCreation = document.getElementById('clanCreation');
-const clanLeader = document.getElementById('clanLeader');
-const clanMembers = document.getElementById('clanMembers');
-
-
-let leaderName = '';
-
-async function getClan() {
-
- //So here we check the tag of the clan in the url
- let url = window.location.href;
- const sliceIndicator = url.indexOf('/clans');
-// The slice has + 7 because thats the amount of characters in "/clans/" yes with two /, not one!
- let findClanTag = url.slice(sliceIndicator + 7, sliceIndicator + 10);
- let clanTag = await findClanTag.replace(/\?m|\?/gm,'');
-
- // We compare the url TAG with the TAGS available in getAllClans and find the clan leader this way
-
- // TODO: Change this hardcoded url into something with env
- const response = await fetch(`https://api.faforever.com/data/clan?include=memberships.player&filter=tag==${clanTag}`);
- const fetchData = await response.json();
-
- const leaderID = fetchData.data[0].relationships.leader.data.id;
-
- fetchData.included.forEach((element, index) => {
- if (index % 2 !== 0) {
- if (element.id === leaderID) {
- leaderName = element.attributes.login;
- }
- }
- });
-
-
- //verifies if user is a member, which allows them to leave the clan
- const clanMember = document.getElementById('iAmMember');
- const isMember = url.indexOf('?member');
- let verifyMembership = url.slice(isMember + 8);
- if (verifyMembership === 'true') {
- clanMember.style.display = 'block';
- }
- return fetchData;
-}
-setTimeout( ()=> {
- getClan()
- .then(fetchData => {
-
- const { attributes} = fetchData.data[0];
- clanName.insertAdjacentHTML('afterbegin',
- `${attributes.name}`);
- clanDescription.insertAdjacentHTML('afterbegin',
- `${attributes.description}`);
- clanTag.insertAdjacentHTML('afterbegin',
- `Welcome to "${attributes.tag}"`);
- //clanLeader.insertAdjacentHTML('afterbegin',
- // `${fetchData.data[0].attributes.id}`);
- clanCreation.insertAdjacentHTML('afterbegin',
- `Created on ${attributes.createTime.slice(0, 10)}`);
- clanLeader.insertAdjacentHTML('afterbegin',
- `Led by ${leaderName}`);
-
- for (let i = 0; i < fetchData.included.length; i++) {
- if (i % 2 !== 0) {
- clanMembers.insertAdjacentHTML('afterbegin',
- `
${fetchData.included[i].attributes.login} `);
- }
- }
- });
-
-},750);
diff --git a/public/styles/site/clans.sass b/public/styles/site/clans.sass
index d3f94d76..3c38a387 100644
--- a/public/styles/site/clans.sass
+++ b/public/styles/site/clans.sass
@@ -178,15 +178,6 @@ input
textarea
width: 40vw
- .clanManagementDanger
- background-color: variables.$Cybran-dark
- border-radius: 20px
- ul
- text-align: center
- li
- display: inline-block
- list-style: none
- text-align: left
.clanManagementTable
padding: 1.5em
display: inline-block
diff --git a/routes/views/clans/get/clans.js b/routes/views/clans/get/clans.js
new file mode 100644
index 00000000..e88c966c
--- /dev/null
+++ b/routes/views/clans/get/clans.js
@@ -0,0 +1,29 @@
+exports = module.exports = function (req, res) {
+ let flash = {};
+ if (req.query.flash) {
+
+ flash.class = 'alert-success';
+ flash.type = 'Success!';
+ switch (req.query.flash) {
+ case 'leave':
+ flash.messages = 'You left your clan.';
+ break;
+
+ case 'destroy':
+ flash.messages = 'You deleted your clan.';
+ break;
+
+ case 'transfer':
+ flash.messages = `You have transferred your clan to ${req.query.newLeader}.`;
+ break;
+
+ case 'error':
+ flash.class = 'alert-danger';
+ flash.messages = 'There was an issue with your request.';
+ flash.type = 'Error!';
+ break;
+ }
+ }
+ res.render('clans', {flash: flash});
+
+};
diff --git a/routes/views/clans/get/create.js b/routes/views/clans/get/create.js
index 4b6a13eb..5a4ca878 100644
--- a/routes/views/clans/get/create.js
+++ b/routes/views/clans/get/create.js
@@ -10,10 +10,10 @@ exports = module.exports = function(req, res) {
request.get(
{
- url: process.env.API_URL + '/clans/me',
- headers: {
- 'Authorization': 'Bearer ' + req.user.data.attributes.token
- }
+ url: process.env.API_URL + '/clans/me',
+ headers: {
+ 'Authorization': 'Bearer ' + req.user.token
+ }
},
function (err, childRes, body) {
diff --git a/routes/views/clans/get/getClan.js b/routes/views/clans/get/getClan.js
new file mode 100644
index 00000000..371454b0
--- /dev/null
+++ b/routes/views/clans/get/getClan.js
@@ -0,0 +1,64 @@
+const axios = require('axios');
+require('dotenv').config();
+exports = module.exports = function(req, res) {
+
+ if (!req.query.tag) res.redirect('../clans?flash=error');
+ else {
+
+
+ //We call the API and get the info needed
+ axios.get(`${process.env.API_URL}/data/clan?include=memberships.player&filter=tag==${req.query.tag.toLowerCase()}`
+ ).then(response => {
+ const {attributes} = response.data.data[0];
+ const {name, description, createTime} = attributes;
+
+ // first lets check user is logged in and has a clan
+ if (req.user && req.user.data.attributes.clan !== undefined) {
+ // lets check if the user belongs to the clan
+ if (req.user.data.attributes.clan.tag.toLowerCase() === req.query.tag.toLowerCase()) {
+ res.locals.leaveButton = true;
+ }
+ }
+
+ //We set the values as local variables in our response
+ res.locals.clanName = name;
+ res.locals.clanDescription = description;
+ res.locals.clanCreation = createTime.slice(0, 10);
+ res.locals.clanTag = req.query.tag.toUpperCase();
+
+
+ //We add in the clan members
+ let clanMembers = [];
+ response.data.included.forEach((member, index) => {
+ // We only allow odd numbers because the API brings extra information on even numbers that don't include a members login/username
+ if (index % 2 !== 0) {
+ clanMembers.push(member.attributes.login);
+ }
+ });
+ res.locals.clanMembers = clanMembers;
+
+ //We find the clan leader
+ const leaderID = response.data.data[0].relationships.leader.data.id;
+ response.data.included.forEach((element, index) => {
+ if (index % 2 !== 0) {
+ if (element.id === leaderID) {
+ res.locals.clanLeaderName = element.attributes.login;
+ }
+ }
+ });
+
+
+
+
+ }).catch((e) => {
+
+ res.redirect('../clans?flash=error');
+
+ }).finally(() => {
+
+
+
+ res.render('clans/getClan');
+ });
+ }
+};
diff --git a/routes/views/clans/get/manage.js b/routes/views/clans/get/manage.js
index 5bcd4ab6..8a1ac814 100755
--- a/routes/views/clans/get/manage.js
+++ b/routes/views/clans/get/manage.js
@@ -1,134 +1,120 @@
-const request = require('request');
-
-exports = module.exports = function(req, res) {
-
- let 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;
- }
-
- // In case the user has just generated an invite link
- if (req.query.invitation_id) {
- flash = {};
- flash.class = 'alert-invite';
-
- flash.messages = [
- {msg:
- ` Right click on me and copy the invitation link
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!';
-
- let buff = Buffer.from(JSON.stringify(flash));
- let 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`);
+const axios = require("axios");
+const error = require("../../account/post/error");
+
+exports = module.exports = function (req, res) {
+
+ let flash = {};
+ let clanMembershipId = null;
+ try {
+ clanMembershipId = req.user.data.attributes.clan.membershipId;
+ } catch (e) {
+ // The user doesnt belong to a clan
+ res.redirect('../clans');
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;
-
- let members = {};
-
- for (k in clan.included){
- switch(clan.included[k].type){
- case "player":
- const 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
+ }
+
+
+ axios.get(`${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`, null,
+ {
+ headers: {'Authorization': `Bearer ${req.user.token}`},
+
+ }).then(response => {
+
+ let clan = response.data
+
+ // Not the leader! Shouldn't be able to manage stuff
+ if (clan.data.relationships.leader.data.id != req.user.data.attributes.userId) {
+ res.redirect(`/clans/getClan?tag=${req.user.data.attributes.clan.tag}`);
+ } else {
+
+
+ // Lets create the schema for all the members and clan descriptions
+ res.locals.clan_name = clan.data.attributes.name;
+ res.locals.clan_tag = clan.data.attributes.tag;
+ res.locals.clan_description = clan.data.attributes.description;
+ res.locals.clan_create_time = clan.data.attributes.createTime;
+ res.locals.me = req.user.data.attributes.userId;
+ res.locals.clan_id = clan.data.id;
+
+ let members = {};
+
+ for (k in clan.included) {
+ switch (clan.included[k].type) {
+ case "player":
+ const 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) {
+ res.locals.founder_name = player.attributes.login
+ }
+ break;
+
+ case "clanMembership":
+ const membership = clan.included[k];
+ const 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;
+ }
+ }
+ res.locals.clan_members = members;
+
+ // Lets check the different flash types
+ if (req.query.flash) {
+ flash.class = 'alert-success';
+ flash.type = 'Success!';
+ switch (req.query.flash) {
+
+ case 'created':
+ flash.messages = 'You have created your clan.';
+ break;
+
+ case 'kick':
+ flash.messages = `You have kicked ${req.query.kickPlayer}.`;
+ break;
+
+ case 'update':
+ flash.messages = `You have updated your clan information.`;
+ break;
+
+
+ case 'error':
+ flash.class = 'alert-danger';
+ flash.messages = 'There was an error with your request.';
+ flash.type = 'Error!';
+ break;
+ case 'alreadyTaken':
+ flash.class = 'alert-danger';
+ flash.messages = 'The clan name/tag is already taken. Choose a different one.';
+ flash.type = 'Error!';
+ break;
+ }
}
- break;
- case "clanMembership":
- const membership = clan.included[k];
- const 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;
+ //Lets check if they tried inviting an user
+ if (req.query.invitation_id && req.query.invitation_id !== 'error') {
+
+ flash.class = 'alert-invite';
+ flash.hasHTML = `${process.env.HOST}/clans/accept_invite?i=${req.query.invitation_id}`;
+ flash.type = 'invite';
+ } else if (req.query.invitation_id === 'error') {
+ flash.class = 'alert-danger';
+ flash.messages = `User isn't a valid username (check your spelling). If error continues contact support`;
+ flash.type = 'Error!';
+ }
+ res.render('clans/manage', {flash: flash});
}
- }
-
- locals.clan_members = members;
-
- 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){
- let buff = Buffer.from(req.query.flash, 'base64');
- let 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"}];
- }
- }
+ }).catch((e) => {
+ console.log(e);
+ error.parseApiErrors(e.response, flash);
+ res.render('clans/manage', {flash: flash});
+
+
+ });
- // Render the view
- res.render('clans/manage', {flash: flash});
- }
- );
};
diff --git a/routes/views/clans/post/create.js b/routes/views/clans/post/create.js
index 8c43d917..18ac900c 100755
--- a/routes/views/clans/post/create.js
+++ b/routes/views/clans/post/create.js
@@ -1,130 +1,66 @@
let flash = {};
-let request = require('request');
-const {check, validationResult} = require('express-validator');
+const axios = require('axios');
+const {body, validationResult} = require('express-validator');
+const error = require("../../account/post/error");
+
+exports = module.exports = [
+
+ // validate the input
+ body('clan_tag', 'Your clan tag is too long (max 3 characters)').notEmpty().isLength({max: 3}),
+ body('clan_description', 'Your clan description is too long (max 1000 characters)').notEmpty().isLength({max: 1000}),
+ body('clan_name', 'Your clan name is too long (max 40 characters)').isLength({max: 40}),
+ async (req, res) => {
+ // check the validation object for errors
+ if (!validationResult(req).isEmpty()) error.errorChecking(req, res, 'clans/create');
+ // No errors in form, continue ahead
+ else {
+
+ // Take variables from form
+ const clanName = req.body.clan_name;
+ const clanTag = req.body.clan_tag;
+ const clanDescription = req.body.clan_description;
+
+ // We check if the clan already exists
+ let clanExists = '';
+ await axios.get(`${process.env.API_URL}/data/clan?filter=name=="${clanName}",tag=="${clanTag}"`)
+ .then(response => {
+ clanExists = !response.data.data[0];
+ }).catch(e => {
+ error.parseApiErrors(e.response, flash);
+ });
+ if (!clanExists) {
+ flash.class = 'alert-danger';
+ flash.messages = 'The clan tag/name are already taken. Choose a different one.';
+ flash.type = 'Error!';
+ res.render('clans/create', {flash: flash});
+
+ }
+ // Clan doesn't exist, lets create it!
+ else {
+ axios.post(`${process.env.API_URL}/clans/create?name=${clanName}&tag=${clanTag}&description=${clanDescription}`, null,
+ {
+ headers: {'Authorization': 'Bearer ' + req.user.token}
+ }).then( () => {
+
+ // Refreshing user
+ axios.get(`${process.env.API_URL}/me`, {
+ headers: {
+ 'Authorization': `Bearer ${req.user.token}`,
+ }
+ }).then( () => {
+
+ //Lets update our user
+ error.userUpdate(req, res, '/clans/create' );
+ }).catch(e => {
+ error.parseApiErrors(e.response, flash);
+ });
+
+ }).catch((e) => {
+ error.parseApiErrors(e.response, flash);
+ res.render('clans/create', {flash: flash});
+ });
+ }
-function promiseRequest(url) {
- return new Promise(function (resolve, reject) {
- request(url, function (error, res, body) {
- if (!error && res.statusCode < 300) {
- resolve(body);
- } else {
- reject(error);
- }
- });
- });
-}
-
-exports = module.exports = async function (req, res) {
-
- let locals = res.locals;
-
- locals.formData = req.body || {};
-
- let overallRes = res;
-
- // validate the input
- check('clan_tag', 'Please indicate the clan tag - No special characters and 3 characters maximum').notEmpty().isLength({max: 3});
- check('clan_description', 'Please add a description for your clan').notEmpty().isLength({max: 1000});
- check('clan_name', "Please indicate your clan's name").notEmpty().isLength({max: 40});
-
- // check the validation object for errors
- let errors = validationResult(req);
-
- //Must have client side errors to fix
- if (!errors.isEmpty()) {
- flash.class = 'alert-danger';
- flash.messages = errors;
- flash.type = 'Error!';
-
- let buff = Buffer.from(JSON.stringify(flash));
- let data = buff.toString('base64');
-
- return overallRes.redirect('create?flash=' + data);
- } else {
-
- const clanName = req.body.clan_name;
- const clanTag = req.body.clan_tag;
- const clanDescription = req.body.clan_description;
- const userId = req.body.user_id;
-
- // Let's check first that the name or tag are not taken
- const clanFetchRoute = process.env.API_URL+'/data/clan?filter=name=="'+clanName+'",tag=="'+clanTag+'"';
- let exists = true;
- try {
- const httpData = await promiseRequest(clanFetchRoute);
- exists = JSON.parse(httpData).data.length > 0;
- }
- catch(e){
- flash.class = 'alert-danger';
- flash.messages = [{msg: 'Error while creating the clan '+e}];
- flash.type = 'Error!';
-
- let buff = Buffer.from(JSON.stringify(flash));
- let data = buff.toString('base64');
-
- return overallRes.redirect('create?flash='+data+'&clan_name='+clanName+'&clan_tag='+clanTag+'&clan_description='+clanDescription+'');
- }
-
- const queryUrl =
- process.env.API_URL
- + '/clans/create'
- + '?name=' + encodeURIComponent(clanName)
- + '&tag='+encodeURIComponent(clanTag)
- + '&description='+encodeURIComponent(clanDescription)
- ;
-
- //Run post to endpoint
- request.post({
- url: queryUrl,
- body: "",
- headers: {
- 'Authorization': 'Bearer ' + req.user.data.attributes.token
- }
- }, function (err, res, body) {
-
- let resp;
- let errorMessages = [];
-
- if (res.statusCode !== 200) {
- let msg = 'Error while creating the clan';
- try {
-
- msg += ': ' + JSON.stringify(JSON.parse(res.body).errors[0].detail);
- } catch {
}
- errorMessages.push({msg: msg});
- flash.class = 'alert-danger';
- flash.messages = errorMessages;
- flash.type = 'Error!';
-
- let buff = Buffer.from(JSON.stringify(flash));
- let data = buff.toString('base64');
-
- return overallRes.redirect('create?flash='+data+'&clan_name='+clanName+'&clan_tag='+clanTag+'&clan_description='+clanDescription+'');
- }
-
- // Refreshing user
- request.get({
- url: process.env.API_URL + '/me',
- headers: {
- 'Authorization': 'Bearer ' + req.user.data.attributes.token,
- }
- },
- function (err, res, body) {
- try{
- let user = JSON.parse(body);
- user.data.attributes.token = req.user.data.attributes.token;
- user.data.id = user.data.attributes.userId;
- req.logIn(user, function(err){
- if (err) console.error(err);
- return overallRes.redirect('/clans/manage');
- });
- }
- catch{
- console.error("There was an error updating a session after a clan creation");
- }
- });
-
- });
- }
-}
+ }
+];
diff --git a/routes/views/clans/post/destroy.js b/routes/views/clans/post/destroy.js
index 0caba265..01a42236 100755
--- a/routes/views/clans/post/destroy.js
+++ b/routes/views/clans/post/destroy.js
@@ -1,111 +1,30 @@
-let flash = {};
-let request = require('request');
-const {check, validationResult} = require('express-validator');
-
-function promiseRequest(url) {
- return new Promise(function (resolve, reject) {
- request(url, function (error, res, body) {
- if (!error && res.statusCode < 300) {
- resolve(body);
- } else {
- reject(error);
- }
- });
- });
-}
-
-exports = module.exports = async function (req, res) {
-
- let locals = res.locals;
-
- locals.formData = req.body || {};
-
- let overallRes = res;
-
- // validate the input
- check('clan_id', 'Internal error while processing your query: invalid clan ID').notEmpty();
-
- // check the validation object for errors
- let errors = validationResult(req);
-
- //Must have client side errors to fix
- if (!errors.isEmpty()) {
- flash.class = 'alert-danger';
- flash.messages = errors;
- flash.type = 'Error!';
-
- let buff = Buffer.from(JSON.stringify(flash));
- let data = buff.toString('base64');
-
- return overallRes.redirect('manage?flash=' + data);
- } else {
-
- // Building update query
- const queryUrl =
- process.env.API_URL
- + '/data/clan/' + req.body.clan_id
- ;
-
- //Run post to endpoint
- request.delete({
- url: queryUrl,
- body: "",
- headers: {
- 'Authorization': 'Bearer ' + req.user.data.attributes.token
- }
- }, function (err, res, body) {
-
- let resp;
- let errorMessages = [];
-
- if (res.statusCode != 204) {
- let msg = 'Error while destroying the clan';
- try{
-
- msg += ': '+JSON.stringify(JSON.parse(res.body).errors[0].detail);
- }
- catch{}
- errorMessages.push({msg: msg});
- flash.class = 'alert-danger';
- flash.messages = errorMessages;
- flash.type = 'Error!';
-
- let buff = Buffer.from(JSON.stringify(flash));
- let data = buff.toString('base64');
-
- return overallRes.redirect('manage?flash='+data);
- }
-
- flash = {};
- flash.class = 'alert-success';
- flash.messages = [{msg: 'The clan was successfully destroyed'}];
- flash.type = 'Success!';
-
- let buff = Buffer.from(JSON.stringify(flash));
- let data = buff.toString('base64');
-
- // Refreshing user
- request.get({
- url: process.env.API_URL + '/me',
- headers: {
- 'Authorization': 'Bearer ' + req.user.data.attributes.token,
- }
- },
-
- function (err, res, body) {
- try{
- let user = JSON.parse(body);
- user.data.id = user.data.attributes.userId;
- user.data.attributes.token = req.user.data.attributes.token;
- req.logIn(user, function(err){
- if (err) console.error(err);
- return overallRes.redirect('/clans?flash='+data);
+let axios = require('axios');
+const {body, validationResult} = require('express-validator');
+const error = require("../../account/post/error");
+
+
+exports = module.exports = [
+ // validate the input
+ body('clan_id', 'Internal error while processing your query: invalid clan ID').notEmpty(),
+ (req, res) => {
+ // check the validation object for errors
+ if (!validationResult(req).isEmpty()) error.errorChecking(req, res, 'clans');
+ // No errors in form, continue ahead
+
+ else {
+ //Run post to endpoint
+ axios.delete(`${process.env.API_URL}/data/clan/${req.body.clan_id}`,
+ {
+ headers: {'Authorization': `Bearer ${req.user.token}`}
+ }).then( ()=> {
+
+ // Refreshing user
+ error.userUpdate(req, res, '/clans?flash=destroy');
+
+ }).catch((e) => {
+ res.redirect('manage?flash=error');
});
- }
- catch{
- console.error("There was an error updating a session after a clan destruction");
- }
- });
- });
- }
-}
+ }
+ }
+]
+;
diff --git a/routes/views/clans/post/invite.js b/routes/views/clans/post/invite.js
index 918dcb21..2c25d82b 100644
--- a/routes/views/clans/post/invite.js
+++ b/routes/views/clans/post/invite.js
@@ -1,156 +1,45 @@
-let flash = {};
-const request = require('request');
-const {check, validationResult} = require('express-validator');
+const axios = require('axios');
+const error = require("../../account/post/error");
-function promiseRequest(url) {
- return new Promise(function (resolve, reject) {
- request(url, function (error, res, body) {
- if (!error && res.statusCode < 300) {
- resolve(body);
- } else {
- console.error("Call to " + url + " failed: " + error);
- reject(error);
- }
- });
- });
-}
-function setLongTimeout(func, delayMs) {
- const maxDelay = 214748364-1; // JS Limit for 32 bit integers
-
- if (delayMs > maxDelay) {
- const remainingDelay = delayMs - maxDelay;
-
- // we cut it in smaller, edible chunks
- setTimeout(() => {
- setLongTimeout(func, remainingDelay);
- }, maxDelay);
- }
- else{
- setTimeout(func, delayMs);
- }
-}
-
-exports = module.exports = async function (req, res) {
-
- let locals = res.locals;
-
- locals.formData = req.body || {};
-
- let overallRes = res;
-
-
- // validate the input
- check('invited_player', 'Please indicate the player name').notEmpty();
-
- // check the validation object for errors
- let errors = validationResult(req);
-
- //Must have client side errors to fix
- if (!errors.isEmpty()) {
- flash.class = 'alert-danger';
- flash.messages = errors;
- flash.type = 'Error!';
-
- let buff = Buffer.from(JSON.stringify(flash));
- let data = buff.toString('base64');
-
- return overallRes.redirect('manage?flash=' + data);
- } else {
-
- const clanId = req.body.clan_id;
+exports = module.exports = async (req, res) => {
+ // Let's get the local variables
+ const clanId = req.body.clan_id;
const userName = req.body.invited_player;
-
- // Let's check first that the player exists
- const fetchRoute = process.env.API_URL + '/data/player?filter=login=="' + userName + '"&fields[player]=';
-
- let exists = true;
- let playerData = null;
let playerId = null;
- try {
- const httpData = await promiseRequest(fetchRoute);
- playerData = JSON.parse(httpData).data;
- exists = playerData.length > 0;
- playerId = playerData[0].id;
- }
- catch(e){
- flash.class = 'alert-danger';
- flash.messages = [{msg: 'The player ' + userName + " doesn't seem to exist" + e}];
- flash.type = 'Error!';
-
- let buff = Buffer.from(JSON.stringify(flash));
- let data = buff.toString('base64');
-
- return overallRes.redirect('manage?flash='+data);
- }
-
- const queryUrl =
- process.env.API_URL
- + '/clans/generateInvitationLink'
- + '?clanId=' + encodeURIComponent(clanId)
- + '&playerId=' + encodeURIComponent(playerId)
- ;
-
- //Run post to endpoint
- request.get({
- url: queryUrl,
- body: "",
- headers: {
- 'Authorization': 'Bearer ' + req.user.data.attributes.token
- }
- }, function (err, res, body) {
-
- if (res.statusCode !== 200) {
-
- let errorMessages = [];
- let msg = 'Error while generating the invite link';
- try {
-
- msg += ': ' + JSON.stringify(JSON.parse(res.body).errors[0].detail);
- } catch {
- }
-
- errorMessages.push({msg: msg});
- flash.class = 'alert-danger';
- flash.messages = errorMessages;
- flash.type = 'Error!';
-
- let buff = Buffer.from(JSON.stringify(flash));
- let data = buff.toString('base64');
- return overallRes.redirect('manage?flash='+data);
- }
- else{
- try{
- const token = JSON.parse(res.body).jwtToken;
-
- const id = Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 5).toUpperCase();
-
+ // Let's check first that the player exists
+ await axios.get(`${process.env.API_URL}/data/player?filter=login==${userName}&fields[player]=`)
+ .then(response => {
+
+ // Player exists
+ if (response.data.data[0] ? response.data.data[0] : false) {
+ playerId = response.data.data[0].id;
+
+ } else { // Player doesn't exist
+
+ res.redirect(`manage?invitation_id=error`);
+ }
+ }).catch(e => {
+ console.log(e);
+ res.redirect(`manage?invitation_id=error`);
+ });
+ //Player does exist, lets create the invite link
+ if (playerId !== null) {
+ await axios.get(`${process.env.API_URL}/clans/generateInvitationLink?clanId=${clanId}&playerId=${playerId}`,
+ {
+ headers: {'Authorization': `Bearer ${req.user.token}`},
+ }).then(response => {
+ let data = response.data;
+ const token = data.jwtToken;
+ let id = Math.random().toString(36).replace(/[^a-z]+/g, '').substring(0, 5).toUpperCase();
req.app.locals.clanInvitations[id] = {
- token:token,
- clan:clanId
+ token: token,
+ clan: clanId
};
-
- // We use timeout here because if we delete the invite link whenver the page is GET,
- // then discord and other messaging applications will destroy the link accidentally
- // when pre-fetching the page. So we will delete it later. Regardless if the website is restarted all the links will be
- // killed instantly, which is fine. They are short lived by design.
- const lifespan = process.env.CLAN_INVITES_LIFESPAN_DAYS * 24 * 3600 * 1000;
- setLongTimeout(()=>{
- delete req.app.locals.clanInvitations[id];
- console.log(`Killed invitation with id ${id} after having waited ${lifespan} seconds (${process.env.CLAN_INVITES_LIFESPAN_DAYS} days)`);
- }, lifespan);
-
- return overallRes.redirect('manage?invitation_id='+id);
- }
- catch (e){
- flash.class = 'alert-danger';
- flash.messages = [{msg:"Unkown error while generating the invite link: "+e}];
- flash.type = 'Error!';
- let buff = Buffer.from(JSON.stringify(flash));
- let data = buff.toString('base64');
- return overallRes.redirect('manage?flash='+data);
- }
- }
- });
- }
-}
+ res.redirect(`manage?invitation_id=${id}`);
+ }).catch(e => {
+ console.log(e);
+ res.redirect(`manage?invitation_id=error`);
+ });
+ }
+};
diff --git a/routes/views/clans/post/join.js b/routes/views/clans/post/join.js
index b4e51d6b..d4d69c47 100644
--- a/routes/views/clans/post/join.js
+++ b/routes/views/clans/post/join.js
@@ -1,87 +1,28 @@
-const request = require('request');
+const axios = require("axios");
+const error = require("../../account/post/error");
-exports = module.exports = function(req, res) {
+exports = module.exports = function (req, res) {
- let locals = res.locals;
-
- // locals.section is used to set the currently selected
- // item in the header navigation.
- locals.section = 'clan';
-
+ // item in the header navigation.
let flash = {};
- const overallRes = res;
-
- if (!req.query.token || !req.query.clan_id){
+
+ if (!req.query.token) {
flash.type = 'Error!';
flash.class = 'alert-danger';
flash.messages = [{msg: 'The invitation link is invalid!'}];
+ res.render('/clans', {flash: flash});
+ } else {
+ const token = req.query.token;
- let buff = Buffer.from(JSON.stringify(flash));
- let data = buff.toString('base64');
-
- return res.redirect('/clans?flash='+data+'');
+ axios.post(`${process.env.API_URL}/clans/joinClan?token=${token}`, null,
+ {
+ headers: {'Authorization': `Bearer null`}
+ }).then(() => {
+ // Refreshing user, by going to clan/manage, user is redirected to their own clan.
+ error.userUpdate(req, res, '/clans/manage');
+ }).catch( e => {
+ console.log(e);
+ res.redirect('../clans?flash=error');
+ });
}
-
- const token = req.query.token;
- const clanId = req.query.clan_id;
-
- request.post(
- {
- url: process.env.API_URL + '/clans/joinClan?token='+token,
- headers: {
- 'Authorization': 'Bearer ' + req.user.data.attributes.token
- }
- },
- function (err, childRes, body) {
- let flashData;
- if (childRes.statusCode == 200 || childRes.statusCode == 201){
- flash.class = 'alert-success';
- flash.messages = [
- {msg: "Welcome to your new clan!"}
- ];
- flash.type = 'Success!';
- let buff = Buffer.from(JSON.stringify(flash));
- flashData = buff.toString('base64');
-
- // Refreshing user
- return request.get({
- url: process.env.API_URL + '/me',
- headers: {
- 'Authorization': 'Bearer ' + req.user.data.attributes.token,
- }
- },
-
- function (err, res, body) {
- try{
- let user = JSON.parse(body);
- user.data.id = user.data.attributes.userId;
- user.data.attributes.token = req.user.data.attributes.token;
- req.logIn(user, function(err){
- if (err) console.error(err);
- return overallRes.redirect(`${user.data.attributes.clan.tag}?member=true&flash=${flashData}`);
- });
- }
- catch{
- console.error("There was an error updating a session after an user left a clan");
- }
- });
- }
- else{
- flash.type = 'Error!';
- flash.class = 'alert-danger';
- let msg = 'The invitation is invalid or has expired, or you are already part of a clan';
- try{
- msg += ': '+JSON.stringify(JSON.parse(childRes.body).errors[0].detail);
- } catch{}
-
- flash.messages = [{msg: msg}];
-
- let buff = Buffer.from(JSON.stringify(flash));
- flashData = buff.toString('base64');
-
- return overallRes.redirect('/clans?flash='+flashData+'');
- }
-
- }
- );
};
diff --git a/routes/views/clans/post/kick.js b/routes/views/clans/post/kick.js
index 13914bf1..57a525eb 100755
--- a/routes/views/clans/post/kick.js
+++ b/routes/views/clans/post/kick.js
@@ -1,96 +1,25 @@
-let flash = {};
-let request = require('request');
-const {check, validationResult} = require('express-validator');
+let axios = require('axios');
-function promiseRequest(url) {
- return new Promise(function (resolve, reject) {
- request(url, function (error, res, body) {
- if (!error && res.statusCode < 300) {
- resolve(body);
- } else {
- reject(error);
- }
- });
- });
-}
+exports = module.exports = function (req, res) {
-exports = module.exports = async function (req, res) {
+ // Check if we are missing the member to kick or if someone is trying to kick themselves. Should not happen normally, but you never know
+ if (req.body.membership_id === req.user.data.attributes.clan.membershipId || !req.body.membership_id) {
+ res.redirect('manage?flash=error&error=missingData');
+ } else {
+ const membershipId = req.body.membership_id;
+ const kickedPlayer = req.body.membership_name;
+ //Run post to endpoint
+ axios.delete(`${process.env.API_URL}/data/clanMembership/${membershipId}`, {
+ headers: {'Authorization': `Bearer ${req.user.token}`}
+ }).then(() => {
+ res.redirect(`manage?flash=kick&kickPlayer=${kickedPlayer}`);
- let locals = res.locals;
+ }).catch((e) => {
+ console.log(e);
+ res.redirect(`manage?flash=error`);
- locals.formData = req.body || {};
+ });
- let overallRes = res;
+ }
- // validate the input
- check('clan_id', 'Internal error while processing your query: invalid clan ID').notEmpty();
- check('membership_id', 'Internal error while processing your query: invalid member ID').notEmpty();
-
- // check the validation object for errors
- let errors = validationResult(req);
-
- // Should not happen normally, but you never know
- if (req.body.membership_id == req.user.data.attributes.clan.membershipId) errors = [{msg: "You cannot kick yourself"}];
-
- //Must have client side errors to fix
- if (!errors.isEmpty()) {
- flash.class = 'alert-danger';
- flash.messages = errors;
- flash.type = 'Error!';
-
- let buff = Buffer.from(JSON.stringify(flash));
- let data = buff.toString('base64');
-
- return overallRes.redirect('manage?flash=' + data);
- } else {
-
- // Building update query
- const membershipId = req.body.membership_id;
- const queryUrl =
- process.env.API_URL
- + '/data/clanMembership/' + membershipId
-
- ;
-
- //Run post to endpoint
- request.delete({
- url: queryUrl,
- body: "",
- headers: {
- 'Authorization': 'Bearer ' + req.user.data.attributes.token
- }
- }, function (err, res, body) {
-
- let resp;
- let errorMessages = [];
-
- if (res.statusCode != 204) {
- let msg = 'Error while removing the member';
- try{
-
- msg += ': '+JSON.stringify(JSON.parse(res.body).errors[0].detail);
- }
- catch{}
- errorMessages.push({msg: msg});
- flash.class = 'alert-danger';
- flash.messages = errorMessages;
- flash.type = 'Error!';
-
- let buff = Buffer.from(JSON.stringify(flash));
- let data = buff.toString('base64');
-
- return overallRes.redirect('manage?flash='+data);
- }
-
- flash = {};
- flash.class = 'alert-success';
- flash.messages = [{msg: 'The member was kicked'}];
- flash.type = 'Success!';
-
- let buff = Buffer.from(JSON.stringify(flash));
- let data = buff.toString('base64');
-
- return overallRes.redirect('manage?flash='+data);
- });
- }
-}
+};
diff --git a/routes/views/clans/post/leave.js b/routes/views/clans/post/leave.js
index 2028675f..94ff8bd4 100755
--- a/routes/views/clans/post/leave.js
+++ b/routes/views/clans/post/leave.js
@@ -1,111 +1,25 @@
-let flash = {};
-let request = require('request');
-const {check, validationResult} = require('express-validator');
+const error = require("../../account/post/error");
+let axios = require('axios');
+
+exports = module.exports = function (req, res) {
+ if (!req.user.data.attributes.clan) {
+ res.redirect('../clans?flash=error&error=missingData');
+ } else {
+ const membershipId = req.user.data.attributes.clan.membershipId;
+ //Run post to endpoint
+ axios.delete(`${process.env.API_URL}/data/clanMembership/${membershipId}`, {
+ headers: {
+ 'Authorization': `Bearer ${req.user.token}`
+ }
+ }).then(() => {
+
+ // Refreshing user
+ error.userUpdate(req, res, '/clans?flash=leave');
+
+ }).catch(e => {
+ console.log(e.response);
+ res.redirect(`../clans?flash=error`);
-function promiseRequest(url) {
- return new Promise(function (resolve, reject) {
- request(url, function (error, res, body) {
- if (!error && res.statusCode < 300) {
- resolve(body);
- } else {
- reject(error);
- }
- });
- });
-}
-
-exports = module.exports = async function (req, res) {
-
- let locals = res.locals;
-
- locals.formData = req.body || {};
-
- let overallRes = res;
-
- // validate the input
- check('clan_id', 'Internal error while processing your query: invalid clan ID').notEmpty();
- check('membership_id', 'Internal error while processing your query: invalid member ID').notEmpty();
-
- // check the validation object for errors
- let errors = validationResult(req);
-
- //Must have client side errors to fix
- if (!errors.isEmpty()) {
- flash.class = 'alert-danger';
- flash.messages = errors;
- flash.type = 'Error!';
-
- let buff = Buffer.from(JSON.stringify(flash));
- let data = buff.toString('base64');
-
- return overallRes.redirect('/clans?flash=' + data);
- } else {
-
- // Building update query
- const membershipId = req.body.membership_id;
- const queryUrl = `${process.env.API_URL}/data/clanMembership/${membershipId}`;
-
- //Run post to endpoint
- request.delete({
- url: `${process.env.API_URL}/data/clanMembership/${req.user.data.attributes.clan.membershipId}`,
- headers: {
- 'Authorization': 'Bearer ' + req.user.data.attributes.token
- }
- }, function (err, res, body) {
-
- let resp;
- let errorMessages = [];
-
- if (res.statusCode != 204) {
- let msg = 'Error while leaving the clan';
- try{
-
- msg += ': '+JSON.stringify(JSON.parse(res.body).errors[0].detail);
- }
- catch{
- errorMessages.push({msg: msg});
- flash.class = 'alert-danger';
- flash.messages = errorMessages;
- flash.type = 'Error!';
- }
-
-
- let buff = Buffer.from(JSON.stringify(flash));
- let data = buff.toString('base64');
-
- return overallRes.redirect('/clans?flash='+data);
- }
-
- flash = {};
- flash.class = 'alert-success';
- flash.messages = [{msg: 'You left the clan'}];
- flash.type = 'Success!';
-
- let buff = Buffer.from(JSON.stringify(flash));
- let data = buff.toString('base64');
-
- // Refreshing user
- request.get({
- url: process.env.API_URL + '/me',
- headers: {
- 'Authorization': 'Bearer ' + req.user.data.attributes.token,
- }
- },
-
- function (err, res, body) {
- try{
- let user = JSON.parse(body);
- user.data.id = user.data.attributes.userId;
- user.data.attributes.token = req.user.data.attributes.token;
- req.logIn(user, function(err){
- if (err) console.error(err);
- return overallRes.redirect('/clans?flash='+data);
- });
- }
- catch{
- console.error("There was an error updating a session after an user left a clan");
- }
});
- });
- }
+ }
};
diff --git a/routes/views/clans/post/transfer.js b/routes/views/clans/post/transfer.js
index 82cf178a..8a8b141e 100755
--- a/routes/views/clans/post/transfer.js
+++ b/routes/views/clans/post/transfer.js
@@ -1,159 +1,85 @@
-let flash = {};
-const request = require('request');
-const {check, validationResult} = require('express-validator');
+const axios = require('axios');
+const error = require("../../account/post/error");
-function promiseRequest(url) {
- return new Promise(function (resolve, reject) {
- request(url, function (error, res, body) {
- if (!error && res.statusCode < 300) {
- resolve(body);
- } else {
- reject(error || `Unexpected status code ${res.statusCode}`);
- }
- });
- });
-}
+exports = module.exports = function (req, res) {
-exports = module.exports = async function (req, res) {
+ const clanId = req.body.clan_id;
+ const transferUsername = req.body.transfer_to;
+ let playerId = null;
- let locals = res.locals;
- locals.formData = req.body || {};
- let overallRes = res;
+ // If clan id or the transfer username are missing, then we can't transfer an unknown clan to an unknown clan member.
+ if (!transferUsername || !clanId) res.redirect('manage?flash=error&error=missingData');
+ else {
- // validate the input
- check('transfer_to', 'Please indicate the recipient name').notEmpty();
- check('clan_id', 'Internal error while processing your query: invalid clan ID').notEmpty();
- // check the validation object for errors
- let errors = validationResult(req);
+ // Let's check first that the player exists AND is part of this clan
+ axios.get(`${process.env.API_URL}/data/clan/${clanId}?include=memberships.player&fields[player]=login`)
+ .then(response => {
- //Must have client side errors to fix
- if (!errors.isEmpty()) {
- flash.class = 'alert-danger';
- flash.messages = errors;
- flash.type = 'Error!';
+ // can't transfer clan to yourself
+ if (transferUsername === req.user.data.attributes.userName) res.redirect('manage?flash=error&error=transferToSelf');
- let buff = Buffer.from(JSON.stringify(flash));
- let data = buff.toString('base64');
- return overallRes.redirect('manage?flash=' + data);
- } else {
-
- const clanId = req.body.clan_id;
- const userName = req.body.transfer_to;
+ // Lets make an array of all members
- // Let's check first that the player exists AND is part of this clan
- const fetchRoute = process.env.API_URL+'/data/clan/'+clanId+'?include=memberships.player&fields[player]=login';
-
- let playerId = null;
-
- try {
- if (userName === req.user.data.attributes.userName) throw "You cannot transfer your own clan to yourself";
-
- const httpData = await promiseRequest(fetchRoute);
- clanData = JSON.parse(httpData);
-
- let members = {};
-
- for (k in clanData.included){
- const record = clanData.included[k];
- if (record.type !== "player") continue;
- members[record.attributes.login] = record.id;
- }
-
- if (!members[userName]) throw "User does not exist or is not part of the clan";
- playerId = members[userName];
- }
- catch(e){
- flash.class = 'alert-danger';
- flash.messages = [{msg: 'There was an error during the transfer to ' + userName + ": "+e}];
- flash.type = 'Error!';
- let buff = Buffer.from(JSON.stringify(flash));
- let data = buff.toString('base64');
+ response.data.included.forEach(player => {
+ if (player.type === "player") {
+ if (player.attributes.login === transferUsername) playerId = player.id;
- return overallRes.redirect('manage?flash='+data);
- }
-
-
- // Building update query
- const queryUrl =
- process.env.API_URL
- + '/data/clan/' + clanId
- ;
-
- const newClanObject =
- {
- "data": {
- "type": "clan",
- "id": clanId,
- "relationships": {
- "leader": {
- "data":{
- "id": playerId,
- "type": "player"
}
- }
- }
- }
- };
-
- //Run post to endpoint
- request.patch({
- url: queryUrl,
- body: JSON.stringify(newClanObject),
- headers: {
- 'Authorization': 'Bearer ' + req.user.data.attributes.token,
- 'Content-Type': 'application/vnd.api+json'
- }
- }, function (err, res, body) {
-
- if (res.statusCode != 204) {
-
- let errorMessages = [];
- let msg = 'Error during the ownership transfer';
- try{
- msg += ': '+JSON.stringify(JSON.parse(res.body).errors[0].detail);
+ });
+
+ }).then(() => {
+
+//Lets check our array for our transfer player
+ if (playerId === null) res.redirect('manage?flash=error&error=notClanMember');
+ else {
+
+ const newClanObject =
+ {
+ "data": {
+ "type": "clan",
+ "id": clanId,
+ "relationships": {
+ "leader": {
+ "data": {
+ "id": playerId,
+ "type": "player"
+ }
+ }
+ }
+ }
+ };
+
+ //Run post to endpoint / Transfer clan
+ axios.patch(`${process.env.API_URL}/data/clan/${clanId}`, newClanObject,
+ {
+
+ headers: {
+ 'Authorization': `Bearer ${req.user.token}`,
+ 'Content-Type': 'application/vnd.api+json'
+ }
+ }).then(() => {
+ // Refreshing user
+ error.userUpdate(req, res, `../clans?flash=transfer&newLeader=${transferUsername}`);
+
+ }).catch(e => {
+
+ res.redirect('manage?flash=error');
+ });
}
- catch{}
-
- errorMessages.push({msg: msg});
- flash.class = 'alert-danger';
- flash.messages = errorMessages;
- flash.type = 'Error!';
-
- let buff = Buffer.from(JSON.stringify(flash));
- let data = buff.toString('base64');
-
- return overallRes.redirect('manage?flash='+data);
- }
- else{
- // Refreshing user
- request.get({
- url: process.env.API_URL + '/me',
- headers: {
- 'Authorization': 'Bearer ' + req.user.data.attributes.token,
- }
- },
-
- function (err, res, body) {
- try{
- let user = JSON.parse(body);
- user.data.id = user.data.attributes.userId;
- user.data.attributes.token = req.user.data.attributes.token;
- req.logIn(user, function(err){
- if (err) console.error(err);
- return overallRes.redirect('see?id='+clanId);
- });
- }
- catch{
- console.error("There was an error updating a session after a clan transfer");
- }
- });
- }
- });
- }
-}
+
+
+ }).catch(e => {
+
+ res.redirect('manage?flash=error');
+ });
+
+ }
+
+
+};
diff --git a/routes/views/clans/post/update.js b/routes/views/clans/post/update.js
index 4822433f..8b99b83b 100644
--- a/routes/views/clans/post/update.js
+++ b/routes/views/clans/post/update.js
@@ -1,156 +1,82 @@
-let flash = {};
-let request = require('request');
+let axios = require('axios');
const {check, validationResult} = require('express-validator');
-
-function promiseRequest(url) {
- return new Promise(function (resolve, reject) {
- request(url, function (error, res, body) {
- if (!error && res.statusCode < 300) {
- resolve(body);
- } else {
- reject(error);
- }
- });
- });
-}
-
-exports = module.exports = async function (req, res) {
-
- let locals = res.locals;
-
- locals.formData = req.body || {};
-
- let overallRes = res;
-
- // validate the input
- check('clan_tag', 'Please indicate the clan tag - No special characters and 3 characters maximum').notEmpty().isLength({max: 3});
- check('clan_description', 'Please add a description for your clan').notEmpty().isLength({max: 1000});
- check('clan_name', "Please indicate your clan's name").notEmpty().isLength({max: 64});
- check('clan_id', 'Internal error while processing your query: invalid clan ID').notEmpty();
-
- // check the validation object for errors
- let errors = validationResult(req);
-
- //Must have client side errors to fix
- if (!errors.isEmpty()) {
- flash.class = 'alert-danger';
- flash.messages = errors;
- flash.type = 'Error!';
-
- let buff = Buffer.from(JSON.stringify(flash));
- let data = buff.toString('base64');
-
- return overallRes.redirect('manage?flash=' + data);
- } else {
-
- const newName = req.body.clan_name;
- const newTag = req.body.clan_tag;
- const oldName = req.body.original_clan_name;
- const oldTag = req.body.original_clan_tag;
- const clanDescription = req.body.clan_description;
- const userId = req.body.user_id;
-
- // Is the name taken ?
- try {
- let msg = null;
-
- flash.class = 'alert-danger';
- flash.type = 'Error!';
-
- if (oldName != newName){
- const fetchRoute = process.env.API_URL+'/data/clan?filter=name=="'+encodeURIComponent(newName)+'"';
- const data = await promiseRequest(fetchRoute);
- const exists = JSON.parse(data).data.length > 0;
-
- if (exists) msg = "This name is already taken: "+encodeURIComponent(newName);
- }
- if (oldTag != newTag){
- const fetchRoute = process.env.API_URL+'/data/clan?filter=tag=="'+encodeURIComponent(newTag)+'"';
- const data = await promiseRequest(fetchRoute);
- const exists = JSON.parse(data).data.length > 0;
-
- if (exists) msg = "This tag is already taken: "+encodeURIComponent(newTag);
- }
-
- if (msg){
- flash.messages = [{msg: msg}];
- let buff = Buffer.from(JSON.stringify(flash));
- let data = buff.toString('base64');
- return overallRes.redirect('manage?flash='+data);
- }
- }
- catch(e){
- flash.class = 'alert-danger';
- flash.messages = [{msg: 'Error while updating the clan '+e}];
- flash.type = 'Error!';
-
- let buff = Buffer.from(JSON.stringify(flash));
- let data = buff.toString('base64');
-
- return overallRes.redirect('manage?flash='+data);
- }
-
- // Building update query
- const queryUrl =
- process.env.API_URL
- + '/data/clan/' + req.body.clan_id
- ;
-
- const newClanObject ={
- "data": {
- "type": "clan",
- "id": req.body.clan_id,
- "attributes": {
- "description": clanDescription,
- "name": newName,
- "tag": newTag
- }
- }
- };
-
-
- //Run post to endpoint
- request.patch({
- url: queryUrl,
- body: JSON.stringify(newClanObject),
- headers: {
- 'Authorization': 'Bearer ' + req.user.data.attributes.token,
- 'Content-Type': 'application/vnd.api+json',
- 'Accept': 'application/vnd.api+json'
- }
- }, function (err, res, body) {
-
- let resp;
- let errorMessages = [];
-
- if (res.statusCode != 204) {
- let msg = 'Error while updating the clan';
- try{
-
- msg += ': '+JSON.stringify(JSON.parse(res.body).errors[0].detail);
+const error = require("../../account/post/error");
+
+exports = module.exports = [
+
+ // validate the input
+ check('clan_tag', 'Please indicate the clan tag - No special characters and 3 characters maximum').isLength({max: 3}),
+ check('clan_description', 'Please add a description for your clan').notEmpty().isLength({max: 1000}),
+ check('clan_name', "Please indicate your clan's name").isLength({max: 64}),
+ check('clan_id', 'Internal error while processing your query: invalid clan ID').notEmpty(),
+
+ async (req, res) => {
+ // check the validation object for errors
+ if (!validationResult(req).isEmpty()) error.errorChecking(req, res, 'clans');
+ // No errors in form, continue ahead
+ else {
+
+ const newName = req.body.clan_name;
+ const newTag = req.body.clan_tag;
+ const oldName = req.body.original_clan_name;
+ const oldTag = req.body.original_clan_tag;
+ const clanDescription = req.body.clan_description;
+
+
+ // Is the clan name / clan tag taken ?
+
+ if (oldName !== newName) {
+ await axios.get(`${process.env.API_URL}/data/clan?filter=name=="${newName}"`)
+ .then(response => {
+ console.log(response.data);
+ if (response.data.data.length >= 0) res.redirect('/manage?flash=alreadyTaken');
+ }).catch(e => {
+ console.log(e);
+ res.redirect('/manage?flash=error');
+ });
+
+ }
+ if (oldTag !== newTag) {
+ await axios.get(`${process.env.API_URL}/data/clan?filter=name=="${newTag}"`)
+ .then(response => {
+ console.log(response.data);
+ if (response.data.data.length >= 0) res.redirect('/manage?flash=alreadyTaken');
+ }).catch(e => {
+ console.log(e);
+ res.redirect('/manage?flash=error');
+ });
+ }
+
+ // Building update query
+ const newClanObject = {
+ "data": {
+ "type": "clan",
+ "id": req.body.clan_id,
+ "attributes": {
+ "description": clanDescription,
+ "name": newName,
+ "tag": newTag
+ }
+ }
+ };
+
+
+ //Run post to endpoint
+ axios.patch(`${process.env.API_URL}/data/clan/${req.body.clan_id}`, newClanObject,
+ {
+
+ headers: {
+ 'Authorization': `Bearer ${req.user.token}`,
+ 'Content-Type': 'application/vnd.api+json',
+ 'Accept': 'application/vnd.api+json'
+ }
+ }).then(response => {
+ //Yay we did it
+ res.redirect('/manage?flash=update');
+ }).catch(e => {
+ console.log(e);
+ res.redirect('/manage?flash=error');
+ });
}
- catch{}
- errorMessages.push({msg: msg});
- flash.class = 'alert-danger';
- flash.messages = errorMessages;
- flash.type = 'Error!';
-
- let buff = Buffer.from(JSON.stringify(flash));
- let data = buff.toString('base64');
-
- return overallRes.redirect('manage?flash='+data);
- }
-
-
- flash = {};
- flash.class = 'alert-success';
- flash.messages = [{msg: 'You have successfully updated your clan'}];
- flash.type = 'Success!';
-
- let buff = Buffer.from(JSON.stringify(flash));
- let data = buff.toString('base64');
-
- return overallRes.redirect('manage?flash='+data);
- });
- }
-};
+ }
+];
diff --git a/templates/mixins/flash-messages.pug b/templates/mixins/flash-messages.pug
index d515504a..45cd3edd 100644
--- a/templates/mixins/flash-messages.pug
+++ b/templates/mixins/flash-messages.pug
@@ -1,8 +1,7 @@
mixin flash-messages(messages)
- if flash
- div.alert(class=flash['class'])
- ul.flash-errors
- if flash.messages
- if flash.messages[0]
- if flash.messages[0].msg
- li #{flash.type} !{flash.messages[0].msg}
+ if flash
+ div.alert(class=flash['class'])
+ if flash.messages
+ p #{flash.type} #{flash['messages']}
+ if flash.hasHTML
+ #{flash.hasHTML}
diff --git a/templates/views/clans/accept_invite.pug b/templates/views/clans/accept_invite.pug
index f5a7b6db..7806262f 100644
--- a/templates/views/clans/accept_invite.pug
+++ b/templates/views/clans/accept_invite.pug
@@ -2,18 +2,11 @@ extends ../../layouts/default
include ../../mixins/flash-messages
block bannerMixin
block content
- .containerCenter.text-center
- .row
- .col-md-12
- h1.account-title Accept invitation
- h4.account-subtitle.text-center Click the button below to accept the invitation from #{clanLeaderName} to join #{clanName}
-
- .row
- .col-md-offset-3.col-md-6
+ .containerCenter.text-center
+ h2 Clan Invitation
+ h4 Click the button below to accept the invitation to join the clan #{clanName}.
+
+flash-messages(flash)
- .row
- .col-md-offset-3.col-md-6
form(method='post', action=acceptURL, data-toggle="validator")
- button(type='submit').btn.btn-default.btn-lg.btn-outro.btn-danger Join #{clanName}
-
+ button(type='submit') Join #{clanName}
diff --git a/templates/views/clans/create.pug b/templates/views/clans/create.pug
index 78d8abee..0f1cfd60 100644
--- a/templates/views/clans/create.pug
+++ b/templates/views/clans/create.pug
@@ -4,45 +4,39 @@ include ../../mixins/form/account
block bannerMixin
block content
- .containerCenter.text-center
- .row
- .col-md-12
+ .containerCenter.text-center
+
h1.account-title Create a clan
div
- p You can create your own clan, and then invite other players to join it.
- p Be sure to
- a(href='/rules') review the rules
- | before naming your clan!
- p Offensive clan names will result in an immediate sanction
-
- .row
- .col-md-offset-3.col-md-6
- +flash-messages(flash)
- form(method='post', action="/clans/create", data-toggle="validator")
- input(type='hidden', name="user_id", value=userId)
+ p You can create your own clan, and then invite other players to join it.
+ p Be sure to
+ a(href='/rules') review the rules
+ | before naming your clan!
+ p Offensive clan names will result in an immediate sanction
+ +flash-messages(flash)
+ form(method='post', action="/clans/create", data-toggle="validator")
+ input(type='hidden', name="user_id", value=userId)
- .clanManagement
- .column12
- div.clanManagementItem
- label Name
- input(type='text', name='clan_name', value=clan_name, placeholder='Clan name').form-control
- input(type='hidden', name='original_clan_name', value=clan_name)
- span(aria-hidden='true').glyphicon.form-control-feedback
+ .clanManagement
+ .column12
+ .clanManagementItem
+ label Name
+ input(type='text', required='required', name='clan_name', value=clan_name, placeholder='Clan name').form-control
+ input(type='hidden', name='original_clan_name', value=clan_name)
+ span(aria-hidden='true').glyphicon.form-control-feedback
- div.clanManagementItem
- label Tag:
+ .clanManagementItem
+ label Tag:
- input(type='text', required='required', name='clan_tag', value=clan_tag, placeholder='TAG', style="display:inline;margin-left:5px;margin-right:5px;width:5em;").form-control
- input(type='hidden', name='original_clan_tag', value=clan_tag)
+ input(type='text', required='required', name='clan_tag', value=clan_tag, placeholder='TAG', style="display:inline;margin-left:5px;margin-right:5px;width:5em;").form-control
+ input(type='hidden', name='original_clan_tag', value=clan_tag)
- span(aria-hidden='true').glyphicon.form-control-feedback
- br
- div.clanManagementItem
- label Clan description
- br
- br
- textarea(rows='12', name='clan_description', required='required', placeholder='The description players will see when they look your clan').form-control #{clan_description}
- span(aria-hidden='true').glyphicon.form-control-feedback
+ span(aria-hidden='true')
+ br
+ .clanManagementItem
+ label Clan description
+ br
- .form-actions
- button(type='submit').bigButton Create your Clan
+ textarea(rows='12', name='clan_description', required='required', placeholder='The description players will see when they look your clan').form-control #{clan_description}
+ span(aria-hidden='true')
+ button(type='submit') Create your Clan
diff --git a/templates/views/clans/getClan.pug b/templates/views/clans/getClan.pug
new file mode 100644
index 00000000..8b8e516c
--- /dev/null
+++ b/templates/views/clans/getClan.pug
@@ -0,0 +1,24 @@
+extends ../../layouts/default
+block bannerMixin
+
+block content
+ // Most of this page is generated through its js file, this pug file is just used to put the ids in place
+ .renderClan
+ .renderClanContainer.column12
+ h2 #{clanTag}
+ h1 #{clanName}
+ p #{clanDescription}
+ p Founded on #{clanCreation}
+ h1 Led by #{clanLeaderName} 👑
+
+ if leaveButton
+ form(method='post', action="/clans/leave", onsubmit="return confirm('You will not be able to return in that clan unless invited again. Press OK to confim.');")
+ .formStart
+ input(type='hidden', name='clan_id', value=clan_id)
+ input(type='hidden', name='membership_id', value=my_membership)
+ button(type='submit') Leave my clan
+ h2 Clan Members
+
+ ul.renderClanSubGrid
+ each member in clanMembers
+ li #{member}
diff --git a/templates/views/clans/manage.pug b/templates/views/clans/manage.pug
index b277f998..dc58f3d6 100644
--- a/templates/views/clans/manage.pug
+++ b/templates/views/clans/manage.pug
@@ -3,129 +3,116 @@ include ../../mixins/flash-messages
include ../../mixins/form/account
block bannerMixin
block content
-
- .containerCenter
- .row
- .col-md-12
- h1.account-title Clan Management
- br
- .row
- .col-md-offset-3.col-md-6
- +flash-messages(flash)
-
- .row.important-form
- .col-md-6
- h2 Invite players
- form(method='post',action="/clans/invite")
- p This will generate an invitation link for the player of your choice
- p Be sure to type the player name correctly!
-
- .row.inline-panel
- input(type='hidden', name='clan_id', value=clan_id)
- input(type='text', name='invited_player', placeholder='Player name', style="margin-left:5px;margin-right:5px").form-control
- button(type='submit' onclick="copyTextButton()") Invite
-
-
- br
- h2 Clan Settings
- .col-md-6
- form(method='post',action="/clans/update",data-toggle="validator")
- input(type='hidden', name='clan_id', value=clan_id)
- .clanManagement
- .column12
- div.clanManagementItem
- label Name
- input(type='text', name='clan_name', value=clan_name, placeholder='Clan name').form-control
- input(type='hidden', name='original_clan_name', value=clan_name)
- span(aria-hidden='true').glyphicon.form-control-feedback
-
- div.clanManagementItem
- label Tag:
-
- input(type='text', required='required', name='clan_tag', value=clan_tag, placeholder='TAG', style="display:inline;margin-left:5px;margin-right:5px;width:5em;").form-control
- input(type='hidden', name='original_clan_tag', value=clan_tag)
-
- span(aria-hidden='true').glyphicon.form-control-feedback
- br
- div.clanManagementItem
- label Clan description
- br
- br
- textarea(rows='12', name='clan_description', required='required', placeholder='The description players will see when they look your clan').form-control #{clan_description}
- span(aria-hidden='true').glyphicon.form-control-feedback
-
- .form-actions
- button(type='submit').bigButton Update Clan Settings
-
- .clanManagement
- .column12
- .clanManagementTable(style="overflow:auto;")
- table.table.table-striped.table-hover
- thead
- tr
- th.text-center Player
- th.text-center Joined
- th.text-center Kick member
- tbody
- each member in clan_members
- tr(class= member.id == me ? "leader me" : "")
- td
- if member.id == me
- abbr(title="Leader") 👑
- | #{member.name}
- td #{member.joinedAt}
- td
- if member.id != me
- form(method='post',action="/clans/kick")
- input(type='hidden', name="membership_id", value=member.membershipId)
- input(type='hidden', name='clan_id', value=clan_id)
- button(type='submit').btn Kick
- else
- span
-
- .clanManagement
- .clanManagementDanger.column12
- h1.danger DANGER ZONE
- p The settings below CANNOT be undone. Do not touch these settings unless you are sure about what you are doing.
-
- form(method='post',action="/clans/transfer",data-toggle="validator", onsubmit="return confirm('ALL YOUR RIGHTS OVER THE CLAN WILL BE LOST. Press OK to confirm the clan transfer');")
- input(type='hidden', name='clan_id', value=clan_id)
- h2 Transfer ownership
- p.text-left This operation will transfer the leadership of your clan to a new member.
- br
- p.text-left After the Leadership transfer,
- ul.text-left
- li You can no longer update the clan
- br
- li You can no longer delete the clan
- br
- li You can no longer invite new players
- br
- li You can no longer kick a player
- br
- br
- p.danger By clicking the "transfer" button, you
- b FORFEIT
- | all your rights over this clan in favor of the new owner.
-
- .row.centered-flex
- input(type='text', id="ownership_transfer_textbox", name='transfer_to', placeholder='Member name', style="margin-left:5px;margin-right:5px").form-control
- button(type='submit').btn-danger.btn Transfer clan ownership
-
- form(method='post',action="/clans/destroy", onsubmit="return confirm('THIS OPERATION IS DEFINITIVE. Press OK to confirm you want to delete your clan');")
- input(type='hidden', name='clan_id', value=clan_id)
- br
- br
- h2 Delete the clan
- p.text-left All memberships will be terminated and the clan will be removed. The name and tag of the clan will become free.
- p.danger This operation
- b CANNOT BE CANCELED
-
-
- .row.centered-flex
- button(type='submit').btn-danger.btn Delete my clan
- br
- br
-
-
-
+
+ .clanManagementMain
+ .clanManagementContainer.column12
+ // Display non-html flash message
+ if flash.messages
+ +flash-messages(flash)
+
+
+
+
+
+ .clanManagementContainer.column12
+ h1 Clan Management
+ h2 Invite players
+ form(method='post',action="/clans/invite")
+ p This will generate an invitation link for the player of your choice
+ p Be sure to type the player name correctly!
+ input(type='hidden', name='clan_id', value=clan_id)
+ input(type='text', name='invited_player', placeholder='Player name', required='required')
+ br
+ button(type='submit' onclick="copyTextButton()") Invite Player
+ // We use HTML for the invite button
+ if flash.hasHTML
+ br
+ h2 Invitation link
+ .displayNone
+ #{flash.hasHTML}
+
+
+ button(onclick="copyInviteLink()") Copy invite link to Clipboard
+ p Note: It only works for the user you typed.
+
+
+ .clanManagementContainer.column12
+ h2 Clan Settings
+ form(method='post',action="/clans/update",data-toggle="validator")
+ input(type='hidden', name='clan_id', value=clan_id)
+ label Clan Name
+ input(type='text', name='clan_name', value=clan_name, placeholder='Clan name', required='required')
+ input(type='hidden', name='original_clan_name', value=clan_name)
+ span(aria-hidden='true')
+ label Clan Tag:
+ input(type='text', required='required', name='clan_tag', value=clan_tag, placeholder='TAG')
+ input(type='hidden', name='original_clan_tag', value=clan_tag)
+ span(aria-hidden='true')
+ br
+ label Clan description
+ br
+
+ textarea(rows='12', name='clan_description', required='required', placeholder='The description players will see when they look your clan') #{clan_description}
+ span(aria-hidden='true')
+ br
+
+ button(type='submit') Update Clan Settings
+
+ .clanManagementContainer.column12
+ .clanMembers
+ each member in clan_members
+ .column2
+ p #{member.name}
+ .column1
+ if member.id != me
+ form(method='post',action="/clans/kick")
+ input(type='hidden', name="membership_name", value=member.name)
+ input(type='hidden', name="membership_id", value=member.membershipId)
+ input(type='hidden', name='clan_id', value=clan_id)
+ button(type='submit') Kick
+ else
+ span
+ .clanManagementMain
+ .clanManagementDanger.clanManagementContainer.column12
+ h1 DANGER ZONE
+ p The settings below CANNOT be undone. Do not touch these settings unless you are sure about what you are doing.
+ form(method='post',action="/clans/transfer",data-toggle="validator", onsubmit="return confirm('ALL YOUR RIGHTS OVER THE CLAN WILL BE LOST. Press OK to confirm the clan transfer');")
+ input(type='hidden', name='clan_id', value=clan_id)
+ h2 Transfer ownership
+ p This operation will transfer the leadership of your clan to a new member.
+ br
+ h2 After the Leadership transfer:
+ li You can no longer update the clan
+
+ li You can no longer delete the clan
+
+ li You can no longer invite new players
+
+ li You can no longer kick a player
+ br
+ br
+ p By clicking the "transfer" button, you
+ b FORFEIT
+ | all your rights over this clan in favor of the new owner.
+
+
+ input(type='text', required='required', id="ownership_transfer_textbox", name='transfer_to', placeholder='New clan owner')
+ br
+ button(type='submit') Transfer clan ownership
+
+ form(method='post',action="/clans/destroy", onsubmit="return confirm('THIS OPERATION IS DEFINITIVE. Press OK to confirm you want to delete your clan');")
+ input(type='hidden', name='clan_id', value=clan_id)
+ br
+ br
+ h2 Delete the clan
+ p All memberships will be terminated and the clan will be removed. The name and tag of the clan will become free.
+ p This operation
+ b CANNOT BE CANCELED
+ br
+ button(type='submit') Delete my clan
+ br
+ br
+ // This script makes it so people can copy the invite link with just a click
+ script.
+ function copyInviteLink() {
+ navigator.clipboard.writeText(document.getElementById("inviteLink").getAttribute("href"))}
diff --git a/templates/views/clans/seeClan.pug b/templates/views/clans/seeClan.pug
deleted file mode 100644
index cd8c3d08..00000000
--- a/templates/views/clans/seeClan.pug
+++ /dev/null
@@ -1,27 +0,0 @@
-extends ../../layouts/default
-block bannerMixin
-
-block content
- // Most of this page is generated through its js file, this pug file is just used to put the ids in place
- .renderClan
- .renderClanContainer.column12
- h2#clanTag
- h1#clanName
- p#clanDescription
- p#clanCreation
- h1#clanLeader
-
-
- #iAmMember
- form(method='post', action="/clans/leave", onsubmit="return confirm('You will not be able to return in that clan unless invited again. Press OK to confim.');")
- input(type='hidden', name='clan_id', value=clan_id)
- input(type='hidden', name='membership_id', value=my_membership)
- h2.row.centered-flex
- button(type='submit').danger.btn.btn-lg Leave my clan
- p Clan Members
-
- ul.renderClanSubGrid#clanMembers
-
-
-block js
- script( src="../../js/app/getClans.js")