- added "map recovery" function for corporation maps to /admin page

- increased "max_count" and "max_shared" map limits for "corporation" and "alliance" maps
This commit is contained in:
Mark Friedrich
2017-12-26 20:47:38 +01:00
parent bdefb90d23
commit a5fafa2b02
18 changed files with 315 additions and 122 deletions

View File

@@ -13,6 +13,7 @@ use Controller\Ccp\Sso;
use Model\CharacterModel;
use Model\CorporationModel;
use lib\Config;
use Model\MapModel;
class Admin extends Controller{
@@ -183,6 +184,23 @@ class Admin extends Controller{
$this->initMembers($f3, $character);
break;
case 'maps':
switch($parts[1]){
case 'active':
$objectId = (int)$parts[2];
$value = (int)$parts[3];
$this->activateMap($character, $objectId, $value);
$f3->reroute('@admin(@*=/' . $parts[0] . ')');
break;
case 'delete':
$objectId = (int)$parts[2];
$this->deleteMap($character, $objectId);
$f3->reroute('@admin(@*=/' . $parts[0] . ')');
break;
}
$this->initMaps($f3, $character);
break;
case 'login':
default:
$f3->set('tplPage', 'login');
@@ -230,7 +248,6 @@ class Admin extends Controller{
*/
protected function banCharacter(CharacterModel $character, $banCharacterId, $value){
$banCharacters = $this->filterValidCharacters($character, $banCharacterId);
foreach($banCharacters as $banCharacter){
$banCharacter->ban($value);
$banCharacter->save();
@@ -248,7 +265,7 @@ class Admin extends Controller{
}
/**
* checks whether a $character has admin access rights for $charcterId
* checks whether a $character has admin access rights for $characterId
* -> must be in same corporation
* @param CharacterModel $character
* @param int $characterId
@@ -270,6 +287,52 @@ class Admin extends Controller{
return $characters;
}
/**
* @param CharacterModel $character
* @param int $mapId
* @param int $value
* @throws \Exception\PathfinderException
*/
protected function activateMap(CharacterModel $character, int $mapId, int $value){
$maps = $this->filterValidMaps($character, $mapId);
foreach($maps as $map){
$map->setActive((bool)$value);
$map->save($character);
}
}
/**
* @param CharacterModel $character
* @param int $mapId
* @throws \Exception\PathfinderException
*/
protected function deleteMap(CharacterModel $character, int $mapId){
$maps = $this->filterValidMaps($character, $mapId);
foreach($maps as $map){
$map->erase();
}
}
/**
* checks whether a $character has admin access rights for $mapId
* @param CharacterModel $character
* @param int $mapId
* @return array
* @throws \Exception\PathfinderException
*/
protected function filterValidMaps(CharacterModel $character, int $mapId) : array {
$maps = [];
if($character->role === 'SUPERADMIN'){
if($filterMaps = MapModel::getAll([$mapId])){
$maps = $filterMaps;
}
}else{
$maps = $character->getCorporation()->getMaps([$mapId], ['addInactive' => true, 'ignoreMapCount' => true]);
}
return $maps;
}
/**
* get log file for "admin" logs
* @param string $type
@@ -287,10 +350,8 @@ class Admin extends Controller{
*/
protected function initMembers(\Base $f3, CharacterModel $character){
$data = (object) [];
if($characterCorporation = $character->getCorporation()){
$corporations = [];
switch($character->role){
case 'SUPERADMIN':
if($accessCorporations = CorporationModel::getAll(['addNPC' => true])){
@@ -304,7 +365,7 @@ class Admin extends Controller{
foreach($corporations as $corporation){
if($characters = $corporation->getCharacters()){
$data->corpMembers[$corporation->name] = $corporation->getCharacters();
$data->corpMembers[$corporation->name] = $characters;
}
}
@@ -317,4 +378,34 @@ class Admin extends Controller{
$f3->set('tplMembers', $data);
}
/**
* init /maps page data
* @param \Base $f3
* @param CharacterModel $character
*/
protected function initMaps(\Base $f3, CharacterModel $character){
$data = (object) [];
if($characterCorporation = $character->getCorporation()){
$corporations = [];
switch($character->role){
case 'SUPERADMIN':
if($accessCorporations = CorporationModel::getAll(['addNPC' => true])){
$corporations = $accessCorporations;
}
break;
case 'CORPORATION':
$corporations[] = $characterCorporation;
break;
}
foreach($corporations as $corporation){
if($maps = $corporation->getMaps([], ['addInactive' => true, 'ignoreMapCount' => true])){
$data->corpMaps[$corporation->name] = $maps;
}
}
}
$f3->set('tplMaps', $data);
}
}

View File

@@ -19,7 +19,7 @@ abstract class BasicModel extends \DB\Cortex {
/**
* Hive key with DB object
* @var string
* @var string|DB\SQL
*/
protected $db = 'DB_PF';

View File

@@ -1081,6 +1081,11 @@ class CharacterModel extends BasicModel {
return array_merge($characterDataBase, $addData);
}
/**
* get all characters
* @param array $characterIds
* @return \DB\CortexCollection
*/
public static function getAll($characterIds = []){
$query = [
'active = :active AND id IN :characterIds',

View File

@@ -127,24 +127,29 @@ class CorporationModel extends BasicModel {
/**
* get all maps for this corporation
* @return MapModel[]
* @param array $mapIds
* @param array $options
* @return array
* @throws \Exception\PathfinderException
*/
public function getMaps(){
public function getMaps($mapIds = [], $options = []){
$maps = [];
$filter = ['active = ?', 1];
$this->filter('mapCorporations',
['active = ?', 1],
['order' => 'created']
);
if( !empty($mapIds) ){
$filter[0] .= ' AND mapId IN (?)';
$filter[] = $mapIds;
}
$this->filter('mapCorporations', $filter, ['order' => 'created']);
if($this->mapCorporations){
$mapCount = 0;
foreach($this->mapCorporations as $mapCorporation){
if(
$mapCorporation->mapId->isActive() &&
$mapCount < Config::getMapsDefaultConfig('corporation')['max_count']
){
$validActive = !$options['addInactive'] ? $mapCorporation->mapId->isActive() : true;
$validMapCount = !$options['ignoreMapCount'] ? $mapCount < Config::getMapsDefaultConfig('corporation')['max_count'] : true;
if($validActive && $validMapCount){
$maps[] = $mapCorporation->mapId;
$mapCount++;
}

View File

@@ -450,7 +450,6 @@ class MapModel extends AbstractMapTrackingModel {
*/
public function afterEraseEvent($self, $pkeys){
$self->clearCacheData();
$self->logActivity('mapDelete');
$self->deleteLogFile();
}
@@ -1335,9 +1334,12 @@ class MapModel extends AbstractMapTrackingModel {
/**
* @param CharacterModel|null $characterModel
* @return false|ConnectionModel
* @return false|MapModel
*/
public function save(CharacterModel $characterModel = null){
/**
* @var $mapModel MapModel
*/
$mapModel = parent::save($characterModel);
// check if map type has changed and clear access objects
@@ -1354,4 +1356,18 @@ class MapModel extends AbstractMapTrackingModel {
return $mapModel;
}
/**
* get all maps
* @param array $mapIds
* @return \DB\CortexCollection
*/
public static function getAll($mapIds = []){
$query = [
'active = :active AND id IN :mapIds',
':active' => 1,
':mapIds' => $mapIds
];
return (new self())->find($query);
}
}

View File

@@ -93,8 +93,8 @@ SEND_RALLY_Mail_ENABLED = 0
[PATHFINDER.MAP.CORPORATION]
LIFETIME = 99999
MAX_COUNT = 3
MAX_SHARED = 3
MAX_COUNT = 5
MAX_SHARED = 4
MAX_SYSTEMS = 100
LOG_ACTIVITY_ENABLED = 1
LOG_HISTORY_ENABLED = 1
@@ -106,7 +106,7 @@ SEND_RALLY_Mail_ENABLED = 0
[PATHFINDER.MAP.ALLIANCE]
LIFETIME = 99999
MAX_COUNT = 3
MAX_COUNT = 4
MAX_SHARED = 2
MAX_SYSTEMS = 100
LOG_ACTIVITY_ENABLED = 0

View File

@@ -62,48 +62,39 @@ define([
* @returns {Array}
*/
let getMapTypes = (filterByUser) => {
let mapTypes = [];
$.each(Init.mapTypes, function(prop, data){
// skip "default" type -> just for 'add' icon
if(data.label.length > 0){
let tempData = data;
tempData.name = prop;
mapTypes.push(tempData);
}
});
let mapTypes = Object.assign({}, Init.mapTypes);
if(filterByUser === true){
let corporationId = Util.getCurrentUserInfo('corporationId');
let allianceId = Util.getCurrentUserInfo('allianceId');
let authorizedMapTypes = [];
// check if character data exists
if(corporationId > 0) {
authorizedMapTypes.push('corporation');
}
if(allianceId > 0){
authorizedMapTypes.push('alliance');
}
let checkMapTypes = ['private', 'corporation', 'alliance'];
// private maps are always allowed
authorizedMapTypes.push('private');
// compare "all" map types with "authorized" types
let tempMapTypes = [];
for(let i = 0; i < mapTypes.length; i++){
for(let j = 0; j < authorizedMapTypes.length; j++){
if(mapTypes[i].name === authorizedMapTypes[j]){
tempMapTypes.push(mapTypes[i]);
break;
for(let i = 0; i < checkMapTypes.length; i++){
let objectId = Util.getCurrentUserInfo(checkMapTypes[i] + 'Id');
if(objectId > 0) {
// check if User could add new map with a mapType
let currentObjectMapData = Util.filterCurrentMapData('config.type.id', Util.getObjVal(mapTypes, checkMapTypes[i] + '.id'));
let maxCountObject = Util.getObjVal(mapTypes, checkMapTypes[i] + '.defaultConfig.max_count');
if(currentObjectMapData.length < maxCountObject){
authorizedMapTypes.push(checkMapTypes[i]);
}
}
}
mapTypes = tempMapTypes;
for(let mapType in mapTypes) {
if(authorizedMapTypes.indexOf(mapType) < 0){
delete( mapTypes[mapType] );
}
}
}
return mapTypes;
// convert to array
let mapTypesFlat = [];
for(let mapType in mapTypes){
mapTypes[mapType].name = mapType;
mapTypesFlat.push(mapTypes[mapType]);
}
return mapTypesFlat;
};
/**

View File

@@ -315,7 +315,7 @@ define([
let selectField = $(this);
let selectValues = selectField.val();
if(selectValues.length > 0){
if(selectValues && selectValues.length > 0){
selectField.parents('.form-group').removeClass('has-error');
}else{
selectField.parents('.form-group').addClass('has-error');

View File

@@ -1295,9 +1295,7 @@ define([
* @returns {number}
*/
let getAreaIdBySecurity = function(security){
let areaId = 0;
switch(security){
case 'H':
areaId = 10;
@@ -1723,6 +1721,21 @@ define([
return currentMapData;
};
/**
* @param path
* @param value
* @returns {boolean}
*/
let filterCurrentMapData = (path, value) => {
let currentMapData = getCurrentMapData();
if(currentMapData){
currentMapData = currentMapData.filter((mapData) => {
return (getObjVal(mapData, path) === value);
});
}
return currentMapData;
};
/**
* delete map data by mapId from currentMapData
* @param mapId
@@ -1775,26 +1788,23 @@ define([
* @param option
* @returns {boolean}
*/
let getCurrentUserInfo = function(option){
let getCurrentUserInfo = (option) => {
let currentUserData = getCurrentUserData();
let userInfo = false;
if(currentUserData){
// user data is set -> user data will be set AFTER the main init request!
let characterData = currentUserData.character;
if(characterData){
if(
option === 'allianceId' &&
characterData.alliance
){
if(option === 'privateId'){
userInfo = characterData.id;
}
if(option === 'allianceId' && characterData.alliance){
userInfo = characterData.alliance.id;
}
if(
option === 'corporationId' &&
characterData.corporation
){
if(option === 'corporationId' && characterData.corporation){
userInfo = characterData.corporation.id;
}
}
@@ -2291,6 +2301,7 @@ define([
getCurrentMapUserData: getCurrentMapUserData,
setCurrentMapData: setCurrentMapData,
getCurrentMapData: getCurrentMapData,
filterCurrentMapData: filterCurrentMapData,
getCurrentMapDataIndex: getCurrentMapDataIndex,
updateCurrentMapData: updateCurrentMapData,
deleteCurrentMapData: deleteCurrentMapData,

File diff suppressed because one or more lines are too long

View File

@@ -62,48 +62,39 @@ define([
* @returns {Array}
*/
let getMapTypes = (filterByUser) => {
let mapTypes = [];
$.each(Init.mapTypes, function(prop, data){
// skip "default" type -> just for 'add' icon
if(data.label.length > 0){
let tempData = data;
tempData.name = prop;
mapTypes.push(tempData);
}
});
let mapTypes = Object.assign({}, Init.mapTypes);
if(filterByUser === true){
let corporationId = Util.getCurrentUserInfo('corporationId');
let allianceId = Util.getCurrentUserInfo('allianceId');
let authorizedMapTypes = [];
// check if character data exists
if(corporationId > 0) {
authorizedMapTypes.push('corporation');
}
if(allianceId > 0){
authorizedMapTypes.push('alliance');
}
let checkMapTypes = ['private', 'corporation', 'alliance'];
// private maps are always allowed
authorizedMapTypes.push('private');
// compare "all" map types with "authorized" types
let tempMapTypes = [];
for(let i = 0; i < mapTypes.length; i++){
for(let j = 0; j < authorizedMapTypes.length; j++){
if(mapTypes[i].name === authorizedMapTypes[j]){
tempMapTypes.push(mapTypes[i]);
break;
for(let i = 0; i < checkMapTypes.length; i++){
let objectId = Util.getCurrentUserInfo(checkMapTypes[i] + 'Id');
if(objectId > 0) {
// check if User could add new map with a mapType
let currentObjectMapData = Util.filterCurrentMapData('config.type.id', Util.getObjVal(mapTypes, checkMapTypes[i] + '.id'));
let maxCountObject = Util.getObjVal(mapTypes, checkMapTypes[i] + '.defaultConfig.max_count');
if(currentObjectMapData.length < maxCountObject){
authorizedMapTypes.push(checkMapTypes[i]);
}
}
}
mapTypes = tempMapTypes;
for(let mapType in mapTypes) {
if(authorizedMapTypes.indexOf(mapType) < 0){
delete( mapTypes[mapType] );
}
}
}
return mapTypes;
// convert to array
let mapTypesFlat = [];
for(let mapType in mapTypes){
mapTypes[mapType].name = mapType;
mapTypesFlat.push(mapTypes[mapType]);
}
return mapTypesFlat;
};
/**

View File

@@ -315,7 +315,7 @@ define([
let selectField = $(this);
let selectValues = selectField.val();
if(selectValues.length > 0){
if(selectValues && selectValues.length > 0){
selectField.parents('.form-group').removeClass('has-error');
}else{
selectField.parents('.form-group').addClass('has-error');

View File

@@ -1295,9 +1295,7 @@ define([
* @returns {number}
*/
let getAreaIdBySecurity = function(security){
let areaId = 0;
switch(security){
case 'H':
areaId = 10;
@@ -1723,6 +1721,21 @@ define([
return currentMapData;
};
/**
* @param path
* @param value
* @returns {boolean}
*/
let filterCurrentMapData = (path, value) => {
let currentMapData = getCurrentMapData();
if(currentMapData){
currentMapData = currentMapData.filter((mapData) => {
return (getObjVal(mapData, path) === value);
});
}
return currentMapData;
};
/**
* delete map data by mapId from currentMapData
* @param mapId
@@ -1775,26 +1788,23 @@ define([
* @param option
* @returns {boolean}
*/
let getCurrentUserInfo = function(option){
let getCurrentUserInfo = (option) => {
let currentUserData = getCurrentUserData();
let userInfo = false;
if(currentUserData){
// user data is set -> user data will be set AFTER the main init request!
let characterData = currentUserData.character;
if(characterData){
if(
option === 'allianceId' &&
characterData.alliance
){
if(option === 'privateId'){
userInfo = characterData.id;
}
if(option === 'allianceId' && characterData.alliance){
userInfo = characterData.alliance.id;
}
if(
option === 'corporationId' &&
characterData.corporation
){
if(option === 'corporationId' && characterData.corporation){
userInfo = characterData.corporation.id;
}
}
@@ -2291,6 +2301,7 @@ define([
getCurrentMapUserData: getCurrentMapUserData,
setCurrentMapData: setCurrentMapData,
getCurrentMapData: getCurrentMapData,
filterCurrentMapData: filterCurrentMapData,
getCurrentMapDataIndex: getCurrentMapDataIndex,
updateCurrentMapData: updateCurrentMapData,
deleteCurrentMapData: deleteCurrentMapData,

View File

@@ -0,0 +1,72 @@
<section>
<div class="container col-xs-12">
<div class="row"></div>
<h4><i class="fa fa-fw fa-sitemap"></i>&nbsp;{{ ucfirst(@tplPage) }}</h4>
<repeat group="{{ @tplMaps->corpMaps }}" value="{{ @corpMap }}" key="{{@corpName}}" counter="{{ @corpCount }}">
<div class="row text-center">
<div class="col-xs-12 pf-landing-pricing-panel">
<div class="panel panel-default pricing-big">
<div class="panel-heading text-left">
<h3 class="panel-title">{{ @corpCount }}. {{@corpName}}</h3>
</div>
<div class="panel-body">
<table id="table_id" class="stripe order-column row-border dataTable" data-order="[1, &quot;asc&quot;]" data-length-change="0" data-paging-type="full_numbers">
<thead>
<tr>
<th data-width="50">id</th>
<th>name</th>
<th data-width="50">scope</th>
<th data-width="50">type</th>
<th data-width="80">created</th>
<th data-width="150">created by</th>
<th data-width="80">updated</th>
<th data-width="150">updated by</th>
<th data-width="50">active</th>
<th data-width="40">delete</th>
</tr>
</thead>
<tbody>
<repeat group="{{ @corpMap }}" value="{{ @map }}" counter="{{ @mapCount }}">
<tr>
<td class="text-right">{{ @map->_id }}</td>
<td data-order="{{ @map->name }}" data-search="{{ @map->name }}">{{ @map->name }}</td>
<td>{{ @map->scopeId->label }}</td>
<td>{{ @map->typeId->name }}</td>
<td class="text-right">{{ @map->getFormattedColumn('created') }}</td>
<td class="pf-table-button-sm-cell">
<img src="//image.eveonline.com/Character/{{ @map->createdCharacterId->_id }}_32.jpg" >&nbsp;{{ @map->createdCharacterId->name }}
</td>
<td class="text-right">{{ @map->getFormattedColumn('updated') }}</td>
<td class="pf-table-button-sm-cell">
<img src="//image.eveonline.com/Character/{{ @map->updatedCharacterId->_id }}_32.jpg" >&nbsp;{{ @map->updatedCharacterId->name }}
</td>
<td class="text-right pf-table-button-sm-cell">
<check if="{{ @map->active }}">
<true>
<a class="btn btn-sm btn-warning" href="/admin/{{ @tplPage}}/active/{{ @map->_id }}/0">deactivate</a>
</true>
<false>
<a class="btn btn-sm btn-success" href="/admin/{{ @tplPage}}/active/{{ @map->_id }}/1">activate</a>
</false>
</check>
</td>
<td class="text-right pf-table-button-sm-cell">
<a class="btn btn-sm btn-danger {{ @map->active ? 'disabled' : '' }}" href="/admin/{{ @tplPage}}/delete/{{ @map->_id }}">delete</a>
</td>
</tr>
</repeat>
</tbody>
</table>
</div>
</div>
</div>
</div>
</repeat>
</div>
</section>

View File

@@ -21,10 +21,10 @@
<th data-width="50">share</th>
<th data-width="50">tracking</th>
<th data-width="50">security</th>
<th data-width="90">last login</th>
<th data-width="90">kicked until</th>
<th data-width="80">last login</th>
<th data-width="80">kicked until</th>
<th data-width="90" data-orderable="false">kick</th>
<th data-width="90">banned since</th>
<th data-width="80">banned since</th>
<th data-width="30" data-orderable="false">ban</th>
</tr>
</thead>
@@ -66,7 +66,7 @@
<td class="text-right txt-color {{ @member->securityStatus >= 0 ? 'txt-color-green' : 'txt-color-orange' }}">{{ number_format(round(@member->securityStatus, 2), 2) }}</td>
<td class="text-right">{{ @member->getFormattedColumn('lastLogin') }}</td>
<td class="text-right txt-color txt-color-orange">{{ @member->getFormattedColumn('kicked') }}</td>
<td class="text-center pf-table-button-sm-cell">
<td class="text-right pf-table-button-sm-cell">
<div class="btn-group btn-group-sm" role="group">
<check if="{{ @member->kicked }}">
<true>
@@ -81,7 +81,7 @@
</div>
</td>
<td class="text-right txt-color txt-color-danger">{{ @member->getFormattedColumn('banned') }}</td>
<td class="text-center pf-table-button-sm-cell">
<td class="text-right pf-table-button-sm-cell">
<check if="{{ @member->banned }}">
<true>
<a class="btn btn-sm btn-primary {{ @disableRow ? 'disabled' : '' }}" href="/admin/{{ @tplPage}}/ban/{{ @member->_id }}">revoke</a>

View File

@@ -73,7 +73,7 @@
<div class="col-sm-12 col-xs-6 checkbox">
<input id="{{persistentAliasesId}}" name="persistentAliases" value="1" type="checkbox" {{#persistentAliases}}checked{{/persistentAliases}}>
<label for="{{persistentAliasesId}}">Persistent system aliases
<i class="fa fa-fw fa-question-circle pf-help-light" title="Keep custom aliases after delete)"></i>
<i class="fa fa-fw fa-question-circle pf-help-light" title="Keep custom aliases after delete"></i>
</label>
</div>
</div>

View File

@@ -18,7 +18,7 @@
<ul class="nav navbar-nav navbar-right" role="tablist">
<li class="{{ @tplPage == 'settings' ? 'active' : '' }} disabled"><a href="javascript:void(0);"><i class="fa fa-fw fa-gears"></i>&nbsp;Settings</a></li>
<li class="{{ @tplPage == 'members' ? 'active' : '' }}"><a href="/admin/members"><i class="fa fa-fw fa-users"></i>&nbsp;Members</a></li>
<li class="{{ @tplPage == 'maps' ? 'active' : '' }} disabled"><a href="javascript:void(0);"><i class="fa fa-fw fa-sitemap"></i>&nbsp;Maps</a></li>
<li class="{{ @tplPage == 'maps' ? 'active' : '' }}"><a href="/admin/maps"><i class="fa fa-fw fa-sitemap"></i>&nbsp;Maps</a></li>
<li class="{{ @tplPage == 'activity' ? 'active' : '' }} disabled"><a href="javascript:void(0);"><i class="fa fa-fw fa-line-chart"></i>&nbsp;Activity</a></li>
<li class="{{ @tplPage == 'login' ? 'active' : '' }}"><a href="/admin/login"><i class="fa fa-fw fa-sign-in"></i>&nbsp;SSO</a></li>
</ul>

View File

@@ -271,7 +271,7 @@ select:active, select:hover {
}
&.pf-table-button-sm-cell{
padding: 0;
padding: 0 5px;
}
&.pf-table-counter-cell{