diff --git a/lib/ApiErrors.js b/lib/ApiErrors.js
new file mode 100644
index 00000000..449f01ca
--- /dev/null
+++ b/lib/ApiErrors.js
@@ -0,0 +1,18 @@
+class JavaApiError extends Error
+{
+ constructor(status, url, errors) {
+ super('Failed request "' + url + '" with status "' + status + '"')
+
+ this.status = status
+ this.url = url
+ this.errors = errors
+ }
+
+}
+
+class GenericJavaApiError extends Error
+{
+}
+
+module.exports.JavaApiError = JavaApiError
+module.exports.GenericJavaApiError = GenericJavaApiError
diff --git a/lib/clan/ClanRepository.js b/lib/clan/ClanRepository.js
new file mode 100644
index 00000000..d229cc4f
--- /dev/null
+++ b/lib/clan/ClanRepository.js
@@ -0,0 +1,116 @@
+const {JavaApiError, GenericJavaApiError} = require("../ApiErrors");
+
+class ClanRepository {
+ constructor(javaApiClient, monthsInThePast = 12) {
+ this.javaApiClient = javaApiClient
+ this.monthsInThePast = monthsInThePast
+ }
+
+ getUpdateTimeForApiEntries() {
+ const date = new Date();
+ date.setMonth(date.getMonth() - this.monthsInThePast);
+
+ return date.toISOString()
+ }
+
+ async updateClan(id, name, description, tag) {
+ const newClanObject = {
+ "data": {
+ "type": "clan",
+ "id": id,
+ "attributes": {
+ "description": description,
+ "name": name,
+ "tag": tag
+ }
+ }
+ };
+
+ try {
+ const response = await this.javaApiClient.patch(`/data/clan/${id}`, newClanObject)
+
+ if (response.status !== 200) {
+ throw new Error('ClanRepository::fetchClanMembership failed with response status "' + response.status + '"')
+ }
+
+ return this.mapClanMembership(JSON.parse(response.data))
+ } catch (e) {
+ if (e.response && e.response.data?.errors) {
+ throw new JavaApiError(e.response.status, `patch /data/clan/${id}`, e.response.data.errors)
+ }
+
+ throw GenericJavaApiError('ClanRepository::fetchClanMembership failed')
+ }
+
+
+
+ }
+
+ async fetchClanMembership(clanMembershipId) {
+ let response = await this.javaApiClient.get(`/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`,)
+
+ if (response.status !== 200) {
+ throw new Error('ClanRepository::fetchClanMembership failed with response status "' + response.status + '"')
+ }
+
+ return this.mapClanMembership(JSON.parse(response.data))
+ }
+
+ mapClanMembership(data) {
+ if (typeof data !== 'object' || data === null) {
+ throw new Error('ClanRepository::mapClanMembership malformed response, not an object')
+ }
+
+ if (!data.hasOwnProperty('data')) {
+ throw new Error('ClanRepository::mapClanMembership malformed response, expected "data"')
+ }
+
+ if (typeof data.data !== 'object' || data.data === null) {
+ return null
+ }
+
+ if (typeof data.included !== 'object' || data.included === null) {
+ throw new Error('ClanRepository::mapClanMembership malformed response, expected "included"')
+ }
+
+ const clanMembershipRaw = data.data.attributes
+
+
+ const clanMembership = {
+ clan_id: data.data.id,
+ clan_name: clanMembershipRaw.name,
+ clan_tag: clanMembershipRaw.tag,
+ clan_description: clanMembershipRaw.description,
+ clan_create_time: clanMembershipRaw.createTime,
+ }
+
+ let members = {};
+
+ for (let k in data.included) {
+ switch (data.included[k].type) {
+ case "player":
+ const player = data.included[k];
+ if (!members[player.id]) members[player.id] = {};
+ members[player.id].id = player.id;
+ members[player.id].name = player.attributes.login;
+
+ break;
+
+ case "clanMembership":
+ const membership = data.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;
+ }
+ }
+
+ clanMembership.members = members
+
+ return clanMembership
+ }
+}
+
+module.exports = ClanRepository
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/js/app/members/test.json~ b/public/js/app/members/test.json~
new file mode 100644
index 00000000..58ff2157
--- /dev/null
+++ b/public/js/app/members/test.json~
@@ -0,0 +1 @@
+{"data":{"type":"clan","id":"2354","attributes":{"createTime":"2023-11-10T23:16:32Z","description":"asdasd","name":"asd","tag":"asd","updateTime":"2023-11-10T23:16:32Z","websiteUrl":"http://localhost:8096/clan/2354"},"relationships":{"founder":{"data":{"type":"player","id":"7"}},"leader":{"data":{"type":"player","id":"7"}}}},"included":[{"type":"clanMembership","id":"15594","attributes":{"createTime":"2023-11-10T23:16:32Z"},"relationships":{"player":{"data":{"type":"player","id":"7"}}}},{"type":"player","id":"7","attributes":{"login":"steambie","updateTime":"2023-10-27T10:38:46Z"}}]}
\ No newline at end of file
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/account/post/error.js b/routes/views/account/post/error.js
index 5d2baa9b..d68db080 100644
--- a/routes/views/account/post/error.js
+++ b/routes/views/account/post/error.js
@@ -1,3 +1,5 @@
+const {validationResult} = require('express-validator');
+
module.exports = {
parseApiErrors: function (body, flash) {
let errorMessages = [];
@@ -17,5 +19,32 @@ module.exports = {
flash.class = 'alert-danger';
flash.messages = errorMessages;
flash.type = 'Error!';
- }
+ },
+ errorChecking: (req, res, path) => {
+ let flash = {}
+ let errorArray = [];
+ //We are putting a space in our forEach so that the errors comma don't stick to the next error.
+ validationResult(req).errors.forEach(error => errorArray.push(` ${error.msg}`));
+ flash.class = 'alert-danger';
+ flash.messages = errorArray;
+ flash.type = 'Error!';
+ res.render(path, {flash: flash});
+ },
+ userUpdate: (req, res, path) => {
+ axios.get(`${process.env.API_URL}/me`, {
+ headers: {
+ 'Authorization': `Bearer ${req.user.token}`,
+ }
+ }).then(response => {
+ let user = response.data;
+ user.token = req.user.token;
+ user.data.id = user.data.attributes.userId;
+ req.logIn(user, function (err) {
+ if (err) console.error(err);
+ res.redirect(path);
+ });
+ }).catch(e => {
+ console.log('error updating user')
+ });
+ }
}
diff --git a/routes/views/clanRouter.js b/routes/views/clanRouter.js
index 5000277f..c823249d 100644
--- a/routes/views/clanRouter.js
+++ b/routes/views/clanRouter.js
@@ -1,7 +1,24 @@
-const express = require('express');
-const router = express.Router();
+const express = require('express')
+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.status(503).render('errors/503-known-issue'));
+router.get('/create', middlewares.isAuthenticated(), require('clans/get/create'))
+router.get('/manage', middlewares.isAuthenticated(), require('clans/get/manage'))
+router.get('/accept_invite', middlewares.isAuthenticated(), require('clans/get/accept_invite'))
+router.post('/create', middlewares.isAuthenticated(), require('clans/post/create'))
+router.post('/destroy', middlewares.isAuthenticated(), require('clans/post/destroy'))
+router.post('/invite', middlewares.isAuthenticated(), require('clans/post/invite'))
+router.post('/kick', middlewares.isAuthenticated(), require('clans/post/kick'))
+router.post('/transfer', middlewares.isAuthenticated(), require('clans/post/transfer'))
+router.post('/update', middlewares.isAuthenticated(), require('clans/post/update'))
+router.post('/leave', middlewares.isAuthenticated(), require('clans/post/leave'))
+router.post('/join', middlewares.isAuthenticated(), require('clans/post/join'))
+
+router.get('/', require('clans/get/clans'))
+router.get('/getClan', require('clans/get/getClan'))
+router.get('/*', (req, res) => {
+ let id = req.path.slice(-3)
+ res.redirect(`/clans/getClan?tag=${id}`)
+})
module.exports = router
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..dde80e37 100644
--- a/routes/views/clans/get/create.js
+++ b/routes/views/clans/get/create.js
@@ -1,3 +1,5 @@
+const axios = require("axios");
+
exports = module.exports = function(req, res) {
let locals = res.locals;
@@ -8,19 +10,17 @@ exports = module.exports = function(req, res) {
const request = require('request');
- request.get(
+ axios.get(process.env.API_URL + '/clans/me',
{
- url: process.env.API_URL + '/clans/me',
- headers: {
- 'Authorization': 'Bearer ' + req.user.data.attributes.token
- }
- },
- function (err, childRes, body) {
+ headers: {
+ 'Authorization': 'Bearer ' + req.user.data.attributes.token
+ }
+ }
+ ).then(function (clanInfo) {
- const clanInfo = JSON.parse(body);
if (clanInfo.clan != null){
- res.redirect('/clans/manage');
- return;
+ res.redirect('/clans/manage');
+ return;
}
locals.formData = req.body || {};
@@ -32,21 +32,21 @@ exports = module.exports = function(req, res) {
var flash = null;
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);
- flasg = [{msg: "Unknown error"}];
- }
+ 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);
+ flasg = [{msg: "Unknown error"}];
+ }
}
// Render the view
res.render('clans/create', {flash: flash});
- }
- );
+ })
+ .catch((e) => console.log(e.toString()))
};
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..015398d3 100755
--- a/routes/views/clans/get/manage.js
+++ b/routes/views/clans/get/manage.js
@@ -1,134 +1,128 @@
-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 error = require("../../account/post/error");
+const appConfig = require('../../../../config/app')
+const ClanRepository = require('../../../../lib/clan/ClanRepository')
+const {Axios} = require("axios");
+
+exports = module.exports = async 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
- }
- 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;
-
- }
- }
-
- 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"}];
- }
- }
-
- // Render the view
- res.render('clans/manage', {flash: flash});
}
- );
+ const config = {
+ baseURL: appConfig.apiUrl,
+ headers: {Authorization: `Bearer ${req.user.token}`}
+ };
+ const javaApiClient = new Axios(config)
+ const clanRepository = new ClanRepository(javaApiClient)
+
+ try {
+ const clan = await clanRepository.fetchClanMembership(clanMembershipId)
+
+ return res.render('clans/manage', {flash: flash, clan: clan});
+ } catch (e) {
+ // error.parseApiErrors(e.response, flash);
+ console.log(e.toString())
+ return res.redirect('/');
+ }
+
+ // 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`,
+ // {
+ // headers: {'Authorization': `Bearer ${req.user.token}`},
+ //
+ // }).then(response => {
+ // const 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;
+ // }
+ // }
+ //
+ // // 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;
+ // }
+ // }
+ //
+ //
+ // //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, clan_members: members});
+ // }
+ // }).catch((e) => {
+ // error.parseApiErrors(e.response, flash);
+ // res.render('clans/manage', {flash: flash});
+ // });
};
diff --git a/routes/views/clans/post/create.js b/routes/views/clans/post/create.js
index 8c43d917..65a0d907 100755
--- a/routes/views/clans/post/create.js
+++ b/routes/views/clans/post/create.js
@@ -1,130 +1,71 @@
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_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 {
+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');
}
- 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+'');
- }
+ 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}"`, {
+ headers: {'Authorization': 'Bearer ' + req.user.token}
+ })
+ .then(response => {
+ clanExists = !response.data.data[0];
+ }).catch(e => {
+ console.log(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) => {
+ console.log(e.toString())
+ error.parseApiErrors(e.response, flash);
+ res.render('clans/create', {flash: flash});
+ });
+ }
- // 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..0159124e 100644
--- a/routes/views/clans/post/update.js
+++ b/routes/views/clans/post/update.js
@@ -1,156 +1,48 @@
-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_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");
+const appConfig = require("../../../../config/app");
+const axios = require('axios')
+const ClanRepository = require('../../../../lib/clan/ClanRepository')
+const {JavaApiError} = require("../../../../lib/ApiErrors");
+
+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 clanDescription = req.body.clan_description;
+
+
+ const config = {
+ baseURL: appConfig.apiUrl,
+ headers: {
+ 'Authorization': `Bearer ${req.user.token}`
+ }
+ };
+ const javaApiClient = axios.create(config)
+ const clanRepository = new ClanRepository(javaApiClient)
+
+ try {
+ const clan = await clanRepository.updateClan(req.body.clan_id, newName, clanDescription, newTag)
+
+ return res.redirect('/clans/manage?flash=update');
+ } catch (e) {
+ if (e instanceof JavaApiError) {
+ req.flash('info', 'Flash is back!')
+ }
+ return res.redirect('/clans/manage')
+ }
}
- 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/sessions/.gitkeep b/sessions/.gitkeep
deleted file mode 100644
index e69de29b..00000000
diff --git a/templates/mixins/flash-messages.pug b/templates/mixins/flash-messages.pug
index d515504a..31fbc401 100644
--- a/templates/mixins/flash-messages.pug
+++ b/templates/mixins/flash-messages.pug
@@ -1,8 +1,5 @@
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}
+ div.alert
+ for message, type in messages
+ for message, type in messages
+ p #{type} #{message}
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..8d69c62d 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 message
+ +flash-messages(message)
+
+
+
+
+
+ .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.clan_id)
+ label Clan Name
+ input(type='text', name='clan_name', value=clan.clan_name, placeholder='Clan name', required='required')
+ input(type='hidden', name='original_clan_name', value=clan.clan_name)
+ span(aria-hidden='true')
+ label Clan Tag:
+ input(type='text', required='required', name='clan_tag', value=clan.clan_tag, placeholder='TAG')
+ input(type='hidden', name='original_clan_tag', value=clan.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.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.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.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")