Browse Source

Multi-user: en cours (partie edition)

idleman 3 years ago
parent
commit
f5e3d689f7

+ 42 - 0
action.php

@@ -1510,6 +1510,48 @@ switch ($_['action']){
 		}
 	break;
 
+	/** PERMISSION **/
+	//Récuperation d'une liste de permission
+	case 'core_permission_search':
+		Action::write(function(&$response){
+			global $myUser,$_;
+			User::check_access('core','read');
+
+			$permissions = Permission::loadAll(array('entity'=>$_['entity'],'uid'=>$_['uid']));
+			
+			foreach($permissions as $permission){
+				$row = $permission->toArray();
+				if( !$permission->read ) unset($row['read']);
+				if( !$permission->edit ) unset($row['edit']);
+				if( !$permission->delete ) unset($row['delete']);
+				if( !$permission->configure ) unset($row['configure']);
+				if( !$permission->recursive ) unset($row['recursive']);
+
+				if($permission->targetEntity == 'rank'){
+					$row['target'] = '<i class="far fa-address-card"></i> '.Rank::getById($permission->targetUid)->label;
+				}else{
+					$user = User::byLogin($permission->targetUid);
+					$row['target'] = '<img class="avatar avatar-mini avatar-rounded" src="'.$user->getAvatar().'"> '.$user->fullName();
+				}
+			
+				$response['rows'][] = $row;
+			}
+			
+		});
+	break;
+
+	//Récuperation ou edition d'élément permission
+	case 'core_permission_edit':
+		Action::write(function(&$response){
+			global $myUser,$_;
+			User::check_access('core','edit');
+
+			$permissions = Permission::loadAll(array('uid'=>$_['uid'],'entity'=>$_['entity']));
+			$response['rows']= $permissions;
+		});
+	break;
+	
+
 	/** CUSTOM API */
 	// pour obtenir un schema de toutes les api actives : http://url.com/api/schema?pretty
 	case 'api':

+ 60 - 0
class/Permission.class.php

@@ -0,0 +1,60 @@
+<?php
+/**
+ * Define a permission.
+ * @author Chuck NORRIS
+ * @category Plugin
+ * @license copyright
+ */
+class Permission extends Entity{
+
+	public $id;
+	public $read; //read (Booléen)
+	public $recursive; //recursive (Booléen)
+	public $uid; //uid (Texte)
+	public $entity; //entity (Texte)
+	public $configure; //configure (Booléen)
+	public $delete; //delete (Booléen)
+	public $edit; //edit (Booléen)
+	public $targetEntity; //Entité cible (Texte)
+	public $targetUid; //uid cible (Texte)
+	
+	protected $TABLE_NAME = 'permission';
+	public $fields = array(
+		'id' => 'key',
+		'read' => 'boolean',
+		'recursive' => 'boolean',
+		'uid' => 'string',
+		'entity' => 'string',
+		'configure' => 'boolean',
+		'delete' => 'boolean',
+		'edit' => 'boolean',
+		'targetEntity' => 'string',
+		'targetUid' => 'string'
+	);
+
+	public $links = array(
+	);
+
+	//Colonnes indexées
+	public $indexes = array();
+
+	//Remplis une permission a partir de la modale de base un d'un form custom
+	public static function form($form = null){
+		if(!isset($form)){
+			global $_;
+			$form = $_;
+		}
+		$item = new self();
+		if(isset($form['read']))$item->read = $form['read'];
+		if(isset($form['recursive']))$item->recursive = $form['recursive'];
+		if(isset($form['uid']))$item->uid = $form['uid'];
+		if(isset($form['entity']))$item->entity = $form['entity'];
+		if(isset($form['configure']))$item->configure = $form['configure'];
+		if(isset($form['delete']))$item->delete = $form['delete'];
+		if(isset($form['edit']))$item->edit = $form['edit'];
+		if(isset($form['targetEntity']))$item->targetEntity = $form['targetEntity'];
+		if(isset($form['targetUid']))$item->targetUid = $form['targetUid'];
+		return $item;
+	}
+}
+?>

+ 29 - 0
css/main.css

@@ -1493,6 +1493,9 @@ span.data-mention-object{
 }
 /* FIN COMPOSANT WYSIWYG / TRUMBOWYG */
 
+#permission-modal .modal-dialog{
+	max-width: 800px;
+}
 
 /* COMPOSANT PASSWORD */
 .password-field {
@@ -2655,3 +2658,29 @@ code {
 		display: none;
 	}
 }
+
+
+#permission{
+	max-width: 600px;
+	margin:auto;
+}
+
+#permissions .label-diagonal{
+	display: inline-block;
+    transform: rotate(-70deg);
+    font-size: 9px;
+}
+#permissions .col-target{
+	max-width: 100px;
+}
+#permissions .col-read,
+#permissions .col-edit,
+#permissions .col-delete,
+#permissions .col-configure,
+#permissions .col-recursive
+{
+	max-width: 50px;
+}
+#permissions td,#permissions th{
+	text-align: center;
+}

+ 76 - 0
footer.php

@@ -210,6 +210,82 @@ $cacheVersion = isset($cacheVersion) ? $cacheVersion : SOURCE_VERSION;
 	    </table>
 	</div>
 
+	<!-- Permission modal -->
+
+	<!-- Modal -->
+	<div class="modal fade" id="permission-modal" tabindex="-1" role="dialog"  aria-hidden="true">
+	  <div class="modal-dialog">
+	    <div class="modal-content">
+	      <div class="modal-header">
+	        <h5 class="modal-title" id="exampleModalLabel">Permissions</h5>
+	        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+	          <span aria-hidden="true">&times;</span>
+	        </button>
+	      </div>
+	      <div class="modal-body">
+	       
+		
+				<div class="row">
+					<!-- search results -->
+					<div class="col-xl-12">
+						<table id="permissions" class="table table-striped " data-entity-search="core_permission_search">
+				            <thead>
+				                <tr>
+				                    <th class="col-target">Utilisateur/Rang</th>
+				                    <th class="col-read"><span class="label-diagonal">Lecture</span></th>
+									<th class="col-edit"><span class="label-diagonal">Ecriture</span></th>
+									<th class="col-delete"><span class="label-diagonal">Suppr.</span></th>
+				                    <th class="col-configure"><span class="label-diagonal">Config.</span></th>
+				                    <th class="col-recursive"><span class="label-diagonal">Récursif</span></th>
+				                    <th></th>
+				                </tr>
+				            </thead>
+				            
+			                <thead>
+			                    <tr id="permission-form" data-action="core_permission_save" data-id="">
+			                        <th class="col-target"><input id="target"  class="form-control" placeholder="" value="" data-type="user" data-types="user,rank" type="text"></th>
+			                        <th class="col-read"><input id="read" name="read" class="form-control" placeholder="" value="" type="checkbox" data-type="checkbox"></th>
+			                        <th class="col-edit"><input id="edit" name="edit" class="form-control" placeholder="" value="" type="checkbox" data-type="checkbox"></th>
+			                        <th class="col-delete"><input id="delete" name="delete" class="form-control" placeholder="" value="" type="checkbox" data-type="checkbox"></th>
+			                        
+			                        <th class="col-configure text-center"><input id="configure" name="configure" class="form-control" placeholder="" value="" type="checkbox" data-type="checkbox"></th>
+			                        <th class="col-recursive text-center"><input id="recursive" name="recursive" class="form-control" placeholder="" value="" type="checkbox" data-type="checkbox"></th>
+			                        <th class="text-right"><div onclick="core_permission_save();" class="btn btn-success btn-mini"><i class="fas fa-check"></i></div></th>
+			                    </tr>
+			                </thead>
+				            
+				            <tbody>
+				                <tr data-id="{{id}}" class="hidden">
+					           
+					                <td class="col-target">{{{target}}}</td>
+					                <td class="col-read">{{#read}}<i class="fas fa-check text-success"></i>{{/read}}{{^read}}<i class="fas fa-times text-danger"></i>{{/read}}</td>
+					                <td class="col-edit">{{#edit}}<i class="fas fa-check text-success"></i>{{/edit}}{{^edit}}<i class="fas fa-times text-danger"></i>{{/edit}}</td>
+					                <td class="col-delete">{{#delete}}<i class="fas fa-check text-success"></i>{{/delete}}{{^delete}}<i class="fas fa-times text-danger"></i>{{/delete}}</td>
+					                <td class="col-configure">{{#configure}}<i class="fas fa-check text-success"></i>{{/configure}}{{^configure}}<i class="fas fa-times text-danger"></i>{{/configure}}</td>
+					                <td class="col-recursive">{{#recursive}}<i class="fas fa-check text-success"></i>{{/recursive}}{{^recursive}}<i class="fas fa-times text-danger"></i>{{/recursive}}</td>
+					                
+					                <td class="text-right">
+					                    
+				                            <div class="btn btn-dark btn-mini " onclick="core_permission_delete(this);"><i class="far fa-trash-alt"></i></div>
+					                  
+					                </td>
+				                </tr>
+				           </tbody>
+				        </table>
+
+					</div>
+				</div>
+
+
+	      </div>
+	      <div class="modal-footer">
+	        <button type="button" class="btn btn-secondary" data-dismiss="modal">Fermer</button>
+	      </div>
+	    </div>
+	  </div>
+	</div>
+
+
 	<?php echo Plugin::callHook('application_bottom'); ?>
 	<!-- Bootstrap core JavaScript -->
 	<!-- Placed at the end of the document so the pages load faster -->

+ 96 - 1
js/main.js

@@ -2768,4 +2768,99 @@ function is_phone(){
   	if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(navigatorName)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(navigatorName.substr(0,4))) 
   		return true;
   	return false;
-}
+}
+
+
+/** PERMISSION **/
+//Récuperation d'une liste de permission dans le tableau #permissions
+function core_permission_search(callback){
+	var data = {
+		action:'core_permission_search',
+	};
+	var modal = $('#permission-modal');
+	data.uid = modal.attr('data-uid');
+	data.entity = modal.attr('data-entity');
+
+	$('#permissions').fill(data,function(response){
+		if(callback!=null) callback();
+	});
+}
+
+//Ajout ou modification d'élément permission
+function core_permission_edit(data){
+	
+	var options = $.extend({
+		read : true,
+		edit : true,
+		delete : true,
+		configure : true,
+		recursive : true
+	},data);
+
+	if(!options.save) return $.message('error','Action de sauvegarde non définie');
+	if(!options.delete) return $.message('error','Action de suppression non définie');
+	
+	$('#permission-modal').find('.col-recursive,.col-configure,.col-read,.col-edit,.col-delete').addClass('hidden');
+
+	if(options.recursive) $('#permission-modal').find('.col-recursive').removeClass('hidden');
+	if(options.configure) $('#permission-modal').find('.col-configure').removeClass('hidden');
+	if(options.read) $('#permission-modal').find('.col-read').removeClass('hidden');
+	if(options.edit) $('#permission-modal').find('.col-edit').removeClass('hidden');
+	if(options.delete) $('#permission-modal').find('.col-delete').removeClass('hidden');
+
+	$('#permission-modal').attr('data-save',options.save);
+	$('#permission-modal').attr('data-delete',options.delete);
+	$('#permission-modal').attr('data-entity',data.entity).attr('data-uid',data.uid);
+
+	$('#permission-modal').modal('show');
+	
+
+	core_permission_search();	
+	if(data.uid){
+		$.action({
+			action : 'core_permission_edit',
+			entity : data.entity,
+			uid :  data.uid,
+		},function(r){
+			
+			
+
+		});
+	}
+}
+
+//Ajout ou modification d'élément permission
+function core_permission_save(){
+	var modal = $('#permission-modal');
+	var data = $('#permission-form').toJson();
+	data.action = modal.attr('data-save');
+	data.uid = modal.attr('data-uid');
+	data.entity = modal.attr('data-entity');
+
+	var target = $('#target').data('values');
+	if(target && target.length>0){
+		target = target[0];
+		data.targetEntity = target.entity;
+		data.targetUid = target.uid;
+	}
+
+	$.action(data,function(r){
+		core_permission_search();
+	});
+}
+
+
+//Suppression d'élement permission
+function core_permission_delete(element){
+	if(!confirm('Êtes vous sûr de vouloir supprimer cet item ?')) return;
+	var line = $(element).closest('tr');
+	var modal = $('#permission-modal');
+
+	$.action({
+		action: modal.attr('data-delete'),
+		id: line.attr('data-id')
+	},function(r){
+		line.remove();
+		$.message('info','Item supprimé');
+	});
+}

BIN
plugin/customiser/theme/hackpoint/img/icons/icon-calendar.png


BIN
plugin/customiser/theme/hackpoint/img/icons/icon-clock.png


BIN
plugin/customiser/theme/hackpoint/img/icons/icon-location.png


BIN
plugin/customiser/theme/hackpoint/img/icons/icon-tag.png


BIN
plugin/customiser/theme/hackpoint/img/icons/icon-user.png


+ 34 - 6
plugin/customiser/theme/hackpoint/main.css

@@ -125,18 +125,17 @@ label.check-component input:checked + .box {
     background-color: #343940;
 }
 .table {
-     color: #ebebeb;
-    border-left: 1px solid #343940;
-    border-bottom: 1px solid #343940;
-    border-right: 1px solid #343940;
+    background: #131517;
+    color: #ebebeb;
+    border: 0;
 }
 .table td, .table th {
     padding: .75rem;
     vertical-align: top;
-    border-top: 1px solid #343940;
+    border: 0;
 }
 .table > thead th {
-    border-bottom: 1px solid #343940;
+    border-bottom: 0;
 }
 .table tr > th:first-of-type, .table tr > td:first-of-type {
     border-right: 1px solid #343940;
@@ -466,6 +465,26 @@ div[data-type="dropzone"] > ul > li {
     background-color: rgb(49, 53, 60);
 }
 
+
+div.data-type-user {
+    background-image: url(./img/icons/icon-user.png);
+}
+
+
+input[data-type="date"]{
+    background-image: url('./img/icons/icon-calendar.png');
+}
+input[data-type="hour"]{
+    background-image: url('./img/icons/icon-clock.png');
+}
+div.data-type-tag-list{
+    background-image: url('./img/icons/icon-tag.png');
+}
+input[data-type="location"]{
+  background-image: url('./img/icons/icon-location.png');
+}
+
+
 @font-face {
     font-family: 'Muli';
     src: url('fonts/Muli-ExtraLight.woff2') format('woff2'),
@@ -490,3 +509,12 @@ div[data-type="dropzone"] > ul > li {
     font-style: normal;
 }
 
+
+.table-striped tbody tr:nth-of-type(odd) {
+    background-color: #0d0e0e;
+}
+
+.modal .modal-dialog {
+    max-width: 800px;
+    box-shadow: 0 0 50px rgba(0,0,0,0.5);
+}

+ 36 - 0
plugin/hackpoint/action.php

@@ -73,6 +73,42 @@ switch($_['action']){
 		});
 	break;
 
+
+
+	case 'hackpoint_sketch_permission_save':
+		Action::write(function(&$response){
+			global $myUser,$_;
+			if(!$myUser->can('hackpoint','edit')) throw new Exception("Permissions insuffisantes",403);
+			require_once(__DIR__.SLASH.'Sketch.class.php');
+			
+			$permission = Permission::form();
+			$permission->entity = 'hackpoint';
+
+			$sketch = Sketch::getById($permission->uid);
+			if($sketch->creator!=$myUser->login) throw new Exception("Vous ne pouvez pas définir une permission sur un sketch qui ne vous appartient pas");
+			
+			$permission->save();
+
+		});
+	break;
+
+	//Suppression d'élement permission
+	case 'hackpoint_sketch_permission_delete':
+		Action::write(function(&$response){
+			global $myUser,$_;
+			require_once(__DIR__.SLASH.'Sketch.class.php');
+			$permission = Permission::getById($_['id']);
+			if($permission->entity != 'hackpoint') throw new Exception("Erreur de routage des permissions");
+			
+			$sketch = Sketch::getById($permission->uid);
+			if($sketch->creator!=$myUser->login) throw new Exception("Vous ne pouvez pas définir une permission sur un sketch qui ne vous appartient pas");
+			
+
+			Permission::deleteById($permission->id);
+		});
+	break;
+
+
 	case 'hackpoint_sketch_save_cover':
 	Action::write(function(&$response){
 		global $myUser,$_;

+ 11 - 0
plugin/hackpoint/js/main.js

@@ -163,6 +163,17 @@ function hackpoint_sketch_search(callback){
 	});
 }
 
+function hackpoint_sketch_permission(){
+	core_permission_edit({
+		entity : 'hackpoint',
+		uid : $('#sketch-form').attr('data-id'),
+		recursive : false,
+		configure : false,
+		save : 'hackpoint_sketch_permission_save',
+		delete : 'hackpoint_sketch_permission_delete',
+	});
+}
+
 //Ajout ou modification d'élément sketch
 function hackpoint_sketch_save(){
 

+ 1 - 0
plugin/hackpoint/page.sheet.sketch.php

@@ -73,6 +73,7 @@ if(isset($_['sidebar']) && $_['sidebar'] == 0) $sketchClasses .= ' no-sidebar';
 									<div onclick="" class="btn btn-success" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><i class="fas fa-cogs"></i></div>
 									<div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
 									    <div class="dropdown-item pointer" onclick="hackpoint_sketch_share();"><i class="fas fa-share-alt"></i> Partager</div>
+									    <div class="dropdown-item pointer" onclick="hackpoint_sketch_permission();"><i class="fas fa-users-cog"></i> Droits</div>
 									    <div class="dropdown-item pointer" onclick="hackpoint_sketch_download();"><i class="far fa-file-archive"></i> Télécharger</div>
 									    <div class="btn btn-delete-sketch dropdown-item" title="Supprimer" onclick="hackpoint_sketch_delete(this);"><i class="far fa-trash-alt"></i> Supprimer</div> 
 									</div>