Skip to content

Commit

Permalink
Merge branch 'main' into style/fix-user-highlight
Browse files Browse the repository at this point in the history
  • Loading branch information
zak39 authored Nov 3, 2023
2 parents c20a90e + 45cfe28 commit 1e7ddf0
Show file tree
Hide file tree
Showing 20 changed files with 572 additions and 119 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- Close menu on group rename error message ([#839](https://github.com/arawa/workspace/pull/839))

### Fixed

- Fix/move v300 constant/stable3.0 ( [#845](https://github.com/arawa/workspace/pull/845) )
Expand Down
10 changes: 10 additions & 0 deletions appinfo/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,16 @@
'url' => '/api/group/addUser/{spaceId}',
'verb' => 'POST',
],
[
'name' => 'fileCSV#import',
'url' => '/file/csv/import-data',
'verb' => 'POST',
],
[
'name' => 'fileCSV#getFromFiles',
'url' => '/file/csv/import-from-files',
'verb' => 'POST',
],
[
'name' => 'space#updateColorCode',
'url' => '/workspaces/{spaceId}/color',
Expand Down
13 changes: 8 additions & 5 deletions css/workspace-style.css
Original file line number Diff line number Diff line change
Expand Up @@ -21,23 +21,26 @@
*
*/

th {
table-space-detail {
width: 100%;
margin-top: -25px;
}
.workspace-th {
color: grey;
padding: 5px;
border-bottom: 1px solid lightgray;
}

td {
.workspace-td {
padding: 5px;
border-bottom: 1px solid lightgray;
}

tr {
.workspace-tr {
height: 50px;
padding: 5px;
}

tr:hover {
.workspace-tr:hover {
background-color: var(--color-backgroud-hover) !important;
}

Expand Down
5 changes: 5 additions & 0 deletions docs/dev/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

## [Unreleased]


### Added

- Close menu on group rename error message ([#839](https://github.com/arawa/workspace/pull/839))

### Fixed

- Fix workspace removal issue ( [#838](https://github.com/arawa/workspace/pull/838))
Expand Down
4 changes: 2 additions & 2 deletions l10n/cs.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
"You have not yet created any workspace": "Zatím jste nevytvořili žádný prac. prostor",
"unlimited": "neomezené",
"You may only specify \"unlimited\" or a number followed by \"TB\", \"GB\", \"MB\", or \"KB\" (eg: \"5GB\") as quota": "Jako kvótu je možné zadat pouze „neomezené“ nebo číslo následované „TB“, „GB“, „MB“ nebo „KB“ (příklad: „5GB“).",
"This space or groupfolder already exist. Please, input another space.\nIf \"toto\" space exist, you cannot create the \"tOTo\" space.\nMake sure you the groupfolder doesn\"t exist.": "Tento prostor nebo skupinová složka už existuje. Zadejte jiný prostor.\nPokud exituje např. prostor „toto“, není možné vytvořit prostor „tOTo“.\nOvěřte, že skupinová složka neexistuje.",
"This space or groupfolder already exist. Please, input another space.\nIf \"toto\" space exist, you cannot create the \"tOTo\" space.\nMake sure you the groupfolder doesn\"t exist.": "Tento prostor nebo skupinová složka už existuje. Zadejte jiný prostor.\nPokud exituje např. prostor „toto“, není možné vytvořit prostor „tOTo“.\nOvěřte, že skupinová složka neexistuje."
},
,"pluralForm" :"nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n <= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;"
"pluralForm" :"nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n <= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;"
}
5 changes: 5 additions & 0 deletions l10n/en.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,5 +77,10 @@ OC.L10N.register(
'Network error occured while trying to change the role of user {user}.<br>The error is: {error}': 'Network error occured while trying to change the role of user {user}.<br>The error is: {error}',
'An error occured while trying to update the workspace\'s quota.<br>The error is: {error}': 'An error occured while trying to update the workspace\'s quota.<br>The error is: {error}',
'Network error occured while trying to update the workspace\'s quota.<br>The error is: {error}': 'Network error occured while trying to update the workspace\'s quota.<br>The error is: {error}',
'Wrong file extension. Must be <b>.csv</b>.': 'Wrong file extension. Must be <b>.csv</b>.',
'Invalid file format. Table header doesn\'t contain any of the following values:<br> {values}': 'Invalid file format. Table header doesn\'t contain any of the following values:<br> {values}',
'Something went wrong. Couldn\'t open a file.': 'Quelque chose s\'est mal passé. Impossible d\'ouvrir un fichier.',
'Add users from csv file': 'Ajouter à partir du fichier csv',
'Import csv from Files': 'Importer csv à partir de Files'
},
"nplurals=2; plural=(n > 1)");
7 changes: 6 additions & 1 deletion l10n/fr.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@ OC.L10N.register(
'You have not yet created any workspace': 'Vous n\'avez pas encore créé d\'espace de travail',
'unlimited': 'illimité',
'You may only specify "unlimited" or a number followed by "TB", "GB", "MB", or "KB" (eg: "5GB") as quota': 'Vous devez spécifier le terme "unlimited" ou un nombre suivi de "TB", "GB", "MB" ou "KB" (exemple: "5GB") comme quota.',
'This space or groupfolder already exist. Please, input another space.\nIf "toto" space exist, you cannot create the "tOTo" space.\nMake sure you the groupfolder doesn\'t exist.': 'Cet espace projet ou le dossier du groupe (groupfolder) existe déjà. Saisissez un autre espace, s\'il vous plaît.\nPar exemple, si l\'espace "toto" existe, vous ne pouvez pas créer l\'espace "tOTo".\nAssurez-vous que le groupfolder n\'existe pas.'
'This space or groupfolder already exist. Please, input another space.\nIf "toto" space exist, you cannot create the "tOTo" space.\nMake sure you the groupfolder doesn\'t exist.': 'Cet espace projet ou le dossier du groupe (groupfolder) existe déjà. Saisissez un autre espace, s\'il vous plaît.\nPar exemple, si l\'espace "toto" existe, vous ne pouvez pas créer l\'espace "tOTo".\nAssurez-vous que le groupfolder n\'existe pas.',
'Wrong file extension. Must be <b>.csv</b>.': 'Mauvais format de fichier. Doit être <b>.csv</b>.',
'Invalid file format. Table header doesn\'t contain any of the following values:<br> {values}': 'Format de fichier est invalide. L\'en-tête du tableau ne contient aucune des valeurs suivantes :<br> {values}',
'Something went wrong. Couldn\'t open a file.': 'Quelque chose s\'est mal passé. Impossible d\'ouvrir un fichier.',
'Add users from csv file': 'Ajouter à partir du fichier csv',
'Import csv from Files': 'Importer csv à partir de Files'
},
"nplurals=2; plural=(n > 1)");
8 changes: 6 additions & 2 deletions l10n/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,12 @@
"You may only specify \"unlimited\" or a number followed by \"TB\", \"GB\", \"MB\", or \"KB\" (eg: \"5GB\") as quota": "Vous devez spécifier le terme \"unlimited\" ou un nombre suivi de \"TB\", \"GB\", \"MB\" ou \"KB\" (exemple: \"5GB\") comme quota.",
"There are no users in this space/group yet": "Il n'y a pas encore d'utilisateur dans cet espace de travail",
"Start typing to lookup users": "Commencez à saisir du texte pour rechercher des utilisateurs",
"remove users from selection": "retirer l'utilisateur de la sélection"

"remove users from selection": "retirer l'utilisateur de la sélection",
"Wrong file extension. Must be <b>.csv</b>.": "Mauvais format de fichier. Doit être <b>.csv</b>.",
"Invalid file format. Table header doesn't contain any of the following values:<br> {values}": "Format de fichier est invalide. L'en-tête du tableau ne contient aucune des valeurs suivantes :<br> {values}",
"Something went wrong. Couldn't open a file.": "Quelque chose s'est mal passé. Impossible d'ouvrir un fichier.",
"Add users from csv file": "Ajouter à partir du fichier csv",
"Import csv from Files": "Importer csv à partir de Files"
},
"pluralForm" : "nplurals=2; plural=(n > 1);"
}
187 changes: 187 additions & 0 deletions lib/Controller/FileCSVController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
<?php

/**
* @copyright Copyright (c) 2017 Arawa
*
* @author 2021 Baptiste Fotia <[email protected]>
* @author 2021 Cyrille Bollu <[email protected]>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

namespace OCA\Workspace\Controller;

use OCA\Workspace\Files\Csv;
use OCA\Workspace\Files\InternalFile;
use OCA\Workspace\Files\LocalFile;
use OCA\Workspace\Service\UserService;
use OCA\Workspace\Service\WorkspaceService;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\JSONResponse;
use OCP\Files\IRootFolder;
use OCP\Files\Node;
use OCP\IRequest;
use OCP\IUserManager;
use OCP\IUserSession;

class FileCSVController extends Controller {
private $currentUser;

public function __construct(
string $appName,
IRequest $request,
private IUserManager $userManager,
private WorkspaceService $workspaceService,
private UserService $userService,
// private FileInfo $file,
private IUserSession $userSession,
private IRootFolder $rootFolder,
) {
parent::__construct($appName, $request);
$this->currentUser = $userSession->getUser();
}

/**
* @NoAdminRequired
* @SpaceAdminRequired
* Returns formatted list of existing users of the instance.
*
*/
public function import(): JSONResponse {
$params = $this->request->getParams();
$spaceObj = $params['space'];
$space = json_decode($spaceObj, true);
$file = $this->request->getUploadedFile('file');

if ($this->isCSVMimeType($file)) {
return new JSONResponse(
[
'Wrong file extension. Must be <b>.csv</b>.'
],
Http::STATUS_FORBIDDEN
);
}

$csv = new Csv();

$localFile = new LocalFile($file['tmp_name']);

if (!$csv->hasProperHeader($localFile)) {
return new JSONResponse(
[
'Invalid file format. Table header doesn\'t contain any of the following values:<br>',
[
...$csv::DISPLAY_NAME,
...$csv::ROLE
]
],
Http::STATUS_FORBIDDEN
);
} else {
new JSONResponse(
[
'Something went wrong. Couldn\'t open a file.'
],
Http::STATUS_FORBIDDEN
);
}

$names = $csv->parser($localFile);

$existingNames = array_filter($names, function ($user) {
return $this->userManager->userExists($user['name']);
});

// get list of IUser objects
$users = $this->formatUsers($existingNames);

$data = $this->formatData($users, $space);

return new JSONResponse($data);
}

/**
* @NoAdminRequired
* @SpaceAdminRequired
* Returns formatted list of existing users of the instance.
*
*/
public function getFromFiles():JSONResponse {
$params = $this->request->getParams();
$path = $params['path'];
$spaceObj = $params['space'];
$space = json_decode($spaceObj, true);
$uid = $this->currentUser->getUID();
$folder = $this->rootFolder->getUserFolder($uid);
$file = $folder->get($path);

if ($this->isCSVMimeType($file)) {
return new JSONResponse(['Wrong file extension. Must be <b>.csv</b>.'], Http::STATUS_FORBIDDEN);
}

$fullPath = $file->getInternalPath();
$csv = new Csv();
$internalFile = new InternalFile($fullPath, $file->getStorage());

if (!$csv->hasProperHeader($internalFile)) {
return new JSONResponse(['Invalid file format. Table header doesn\'t contain any of the following values:<br>', [...$csv::DISPLAY_NAME, ...$csv::ROLE]], Http::STATUS_FORBIDDEN);
}

$names = $csv->parser($internalFile);

// filter array to leave only existing users
$existingNames = array_filter($names, function ($user) {
return $this->userManager->userExists($user['name']);
});

$users = $this->formatUsers($existingNames);

$data = $this->formatData($users, $space);

return new JSONResponse($data);
}

private function formatData(array $users, array $space): array {
$data = [];
foreach ($users as $user) {
$role = $user['role'] == "admin" ? "admin" : "user";
$data[] = $this->userService->formatUser($user['user'], $space, $role);
}

return $data;
}

private function formatUsers(array $data): array {
$users = [];
foreach($data as $user) {
$users[] = [
'user' => $this->userManager->get($user['name']),
'role' => $user['role']
];
}
return $users;
}

private function isCSVMimeType(Node|array $file): bool {
if($file instanceof Node) {
return $file->getMimetype() !== 'text/csv';
}

return $file['type'] !== 'text/csv';
}
}
89 changes: 89 additions & 0 deletions lib/Files/Csv.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?php

/**
* @copyright Copyright (c) 2017 Arawa
*
* @author 2021 Baptiste Fotia <[email protected]>
* @author 2021 Cyrille Bollu <[email protected]>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

namespace OCA\Workspace\Files;

use Exception;

class Csv {

public const DISPLAY_NAME = ["username", "displayname", "name"];
public const ROLE = ["role", "status", "userrole"];

private function getIndex(array $haystack, array $needles): int|bool {
$index = null;
foreach($haystack as $key => $value) {
$index = array_search($value, $needles);
if ($index !== false) {
return $index;
}
}
return false;
}

public function parser(ManagerConnectionFileInterface $file) {
$handle = $file->open();

if ($handle === false) {
throw new Exception("Imposible to open the $file->getPath() file.");
}

$users = [];
// rewind($handle);
$tableHeader = fgetcsv($handle, 1000, ","); // ignore the first line
$tableHeader = array_map('strtolower', $tableHeader);

$nameIndex = $this->getIndex($this::DISPLAY_NAME, $tableHeader);
$roleIndex = $this->getIndex($this::ROLE, $tableHeader);

while (($data = fgetcsv($handle, 1000, ",")) !== false) {
$users[] = ['name' => $data[$nameIndex], 'role' => $data[$roleIndex]];
}
$file->close();

return $users;
}

public function hasProperHeader(ManagerConnectionFileInterface $file): bool {
// var_dump($path);
// die();
$res = false;
if (($handle = $file->open()) !== false) {
$tableHeader = fgetcsv($handle, 1000, ",");
$tableHeader = array_map('strtolower', $tableHeader);
// var_dump($tableHeader);
// die();

$nameIndex = $this->getIndex(self::DISPLAY_NAME, $tableHeader);
$roleIndex = $this->getIndex(self::ROLE, $tableHeader);

$res = ($nameIndex !== false) && ($roleIndex !== false);
}

$file->close();

return $res;
}
}
Loading

0 comments on commit 1e7ddf0

Please sign in to comment.