mirror of
https://github.com/grocy/grocy.git
synced 2025-08-08 07:19:32 +00:00
Applied EditorConfig settings to all files
This commit is contained in:
parent
2c966c77fd
commit
3b0d29bed0
2
app.php
2
app.php
@ -67,7 +67,7 @@ if (!empty(GROCY_BASE_PATH))
|
||||
$app->addRoutingMiddleware();
|
||||
$errorMiddleware = $app->addErrorMiddleware(true, false, false);
|
||||
$errorMiddleware->setDefaultErrorHandler(
|
||||
new \Grocy\Controllers\ExceptionController($app, $container)
|
||||
new \Grocy\Controllers\ExceptionController($app, $container)
|
||||
);
|
||||
|
||||
$app->run();
|
||||
|
@ -34,7 +34,7 @@ class BaseController
|
||||
$this->View->set('version', $versionInfo->Version);
|
||||
$this->View->set('releaseDate', $versionInfo->ReleaseDate);
|
||||
|
||||
$localizationService = $this->getLocalizationService();
|
||||
$localizationService = $this->getLocalizationService();
|
||||
$this->View->set('__t', function(string $text, ...$placeholderValues) use($localizationService)
|
||||
{
|
||||
return $localizationService->__t($text, $placeholderValues);
|
||||
@ -98,12 +98,12 @@ class BaseController
|
||||
return $this->render($response, $page, $data);
|
||||
}
|
||||
|
||||
protected function getDatabaseService()
|
||||
protected function getDatabaseService()
|
||||
{
|
||||
return DatabaseService::getInstance();
|
||||
}
|
||||
|
||||
protected function getDatabase()
|
||||
protected function getDatabase()
|
||||
{
|
||||
return $this->getDatabaseService()->GetDbConnection();
|
||||
}
|
||||
@ -128,7 +128,7 @@ class BaseController
|
||||
return CalendarService::getInstance();
|
||||
}
|
||||
|
||||
protected function getSessionService()
|
||||
protected function getSessionService()
|
||||
{
|
||||
return SessionService::getInstance();
|
||||
}
|
||||
@ -143,12 +143,12 @@ class BaseController
|
||||
return StockService::getInstance();
|
||||
}
|
||||
|
||||
protected function getTasksService()
|
||||
protected function getTasksService()
|
||||
{
|
||||
return TasksService::getInstance();
|
||||
}
|
||||
|
||||
protected function getUsersService()
|
||||
protected function getUsersService()
|
||||
{
|
||||
return UsersService::getInstance();
|
||||
}
|
||||
@ -172,6 +172,6 @@ class BaseController
|
||||
{
|
||||
return FilesService::getInstance();
|
||||
}
|
||||
|
||||
|
||||
protected $AppContainer;
|
||||
}
|
||||
|
@ -13,9 +13,9 @@ class BatteriesApiController extends BaseApiController
|
||||
|
||||
public function TrackChargeCycle(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
||||
{
|
||||
User::checkPermission($request, User::PERMISSION_BATTERY_TRACK_CHARGE_CYCLE);
|
||||
User::checkPermission($request, User::PERMISSION_BATTERY_TRACK_CHARGE_CYCLE);
|
||||
|
||||
$requestBody = $request->getParsedBody();
|
||||
$requestBody = $request->getParsedBody();
|
||||
|
||||
try
|
||||
{
|
||||
@ -53,9 +53,9 @@ class BatteriesApiController extends BaseApiController
|
||||
|
||||
public function UndoChargeCycle(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
||||
{
|
||||
User::checkPermission($request, User::PERMISSION_BATTERY_UNDO_TRACK_CHARGE_CYCLE);
|
||||
User::checkPermission($request, User::PERMISSION_BATTERY_UNDO_TRACK_CHARGE_CYCLE);
|
||||
|
||||
try
|
||||
try
|
||||
{
|
||||
$this->ApiResponse($response, $this->getBatteriesService()->UndoChargeCycle($args['chargeCycleId']));
|
||||
return $this->EmptyApiResponse($response);
|
||||
|
@ -17,9 +17,9 @@ class ChoresApiController extends BaseApiController
|
||||
|
||||
try
|
||||
{
|
||||
User::checkPermission($request, User::PERMISSION_CHORE_TRACK);
|
||||
User::checkPermission($request, User::PERMISSION_CHORE_TRACK);
|
||||
|
||||
$trackedTime = date('Y-m-d H:i:s');
|
||||
$trackedTime = date('Y-m-d H:i:s');
|
||||
if (array_key_exists('tracked_time', $requestBody) && (IsIsoDateTime($requestBody['tracked_time']) || IsIsoDate($requestBody['tracked_time'])))
|
||||
{
|
||||
$trackedTime = $requestBody['tracked_time'];
|
||||
@ -31,7 +31,7 @@ class ChoresApiController extends BaseApiController
|
||||
$doneBy = $requestBody['done_by'];
|
||||
}
|
||||
if($doneBy != GROCY_USER_ID)
|
||||
User::checkPermission($request, User::PERMISSION_CHORE_TRACK_OTHERS);
|
||||
User::checkPermission($request, User::PERMISSION_CHORE_TRACK_OTHERS);
|
||||
|
||||
$choreExecutionId = $this->getChoresService()->TrackChore($args['choreId'], $trackedTime, $doneBy);
|
||||
return $this->ApiResponse($response, $this->getDatabase()->chores_log($choreExecutionId));
|
||||
@ -63,9 +63,9 @@ class ChoresApiController extends BaseApiController
|
||||
{
|
||||
try
|
||||
{
|
||||
User::checkPermission($request, User::PERMISSION_CHORE_UNDO);
|
||||
User::checkPermission($request, User::PERMISSION_CHORE_UNDO);
|
||||
|
||||
$this->ApiResponse($response, $this->getChoresService()->UndoChoreExecution($args['executionId']));
|
||||
$this->ApiResponse($response, $this->getChoresService()->UndoChoreExecution($args['executionId']));
|
||||
return $this->EmptyApiResponse($response);
|
||||
}
|
||||
catch (\Exception $ex)
|
||||
@ -78,9 +78,9 @@ class ChoresApiController extends BaseApiController
|
||||
{
|
||||
try
|
||||
{
|
||||
User::checkPermission($request, User::PERMISSION_CHORE_EDIT);
|
||||
User::checkPermission($request, User::PERMISSION_CHORE_EDIT);
|
||||
|
||||
$requestBody = $request->getParsedBody();
|
||||
$requestBody = $request->getParsedBody();
|
||||
|
||||
$choreId = null;
|
||||
if (array_key_exists('chore_id', $requestBody) && !empty($requestBody['chore_id']) && is_numeric($requestBody['chore_id']))
|
||||
|
@ -1,6 +1,5 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Grocy\Controllers;
|
||||
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
@ -12,58 +11,58 @@ use Throwable;
|
||||
|
||||
class ExceptionController extends BaseApiController
|
||||
{
|
||||
/**
|
||||
* @var \Slim\App
|
||||
*/
|
||||
private $app;
|
||||
/**
|
||||
* @var \Slim\App
|
||||
*/
|
||||
private $app;
|
||||
|
||||
public function __construct(\Slim\App $app, \DI\Container $container)
|
||||
{
|
||||
parent::__construct($container);
|
||||
$this->app = $app;
|
||||
}
|
||||
public function __construct(\Slim\App $app, \DI\Container $container)
|
||||
{
|
||||
parent::__construct($container);
|
||||
$this->app = $app;
|
||||
}
|
||||
|
||||
public function __invoke(ServerRequestInterface $request,
|
||||
Throwable $exception,
|
||||
bool $displayErrorDetails,
|
||||
bool $logErrors,
|
||||
bool $logErrorDetails,
|
||||
?LoggerInterface $logger = null)
|
||||
{
|
||||
$response = $this->app->getResponseFactory()->createResponse();
|
||||
public function __invoke(ServerRequestInterface $request,
|
||||
Throwable $exception,
|
||||
bool $displayErrorDetails,
|
||||
bool $logErrors,
|
||||
bool $logErrorDetails,
|
||||
?LoggerInterface $logger = null)
|
||||
{
|
||||
$response = $this->app->getResponseFactory()->createResponse();
|
||||
|
||||
$isApiRoute = string_starts_with($request->getUri()->getPath(), '/api/');
|
||||
if ($isApiRoute) {
|
||||
$status = 500;
|
||||
if ($exception instanceof HttpException) {
|
||||
$status = $exception->getCode();
|
||||
}
|
||||
$data = [
|
||||
'error_message' => $exception->getMessage(),
|
||||
];
|
||||
if ($displayErrorDetails) {
|
||||
$data['error_details'] = [
|
||||
'stack_trace' => $exception->getTraceAsString(),
|
||||
'file' => $exception->getFile(),
|
||||
'line' => $exception->getLine(),
|
||||
];
|
||||
}
|
||||
return $this->ApiResponse($response->withStatus($status), $data);
|
||||
}
|
||||
if ($exception instanceof HttpNotFoundException) {
|
||||
return $this->renderPage($response->withStatus(404), 'errors/404', [
|
||||
'exception' => $exception
|
||||
]);
|
||||
}
|
||||
if ($exception instanceof HttpForbiddenException) {
|
||||
return $this->renderPage($response->withStatus(403), 'errors/403', [
|
||||
'exception' => $exception
|
||||
]);
|
||||
}
|
||||
$isApiRoute = string_starts_with($request->getUri()->getPath(), '/api/');
|
||||
if ($isApiRoute) {
|
||||
$status = 500;
|
||||
if ($exception instanceof HttpException) {
|
||||
$status = $exception->getCode();
|
||||
}
|
||||
$data = [
|
||||
'error_message' => $exception->getMessage(),
|
||||
];
|
||||
if ($displayErrorDetails) {
|
||||
$data['error_details'] = [
|
||||
'stack_trace' => $exception->getTraceAsString(),
|
||||
'file' => $exception->getFile(),
|
||||
'line' => $exception->getLine(),
|
||||
];
|
||||
}
|
||||
return $this->ApiResponse($response->withStatus($status), $data);
|
||||
}
|
||||
if ($exception instanceof HttpNotFoundException) {
|
||||
return $this->renderPage($response->withStatus(404), 'errors/404', [
|
||||
'exception' => $exception
|
||||
]);
|
||||
}
|
||||
if ($exception instanceof HttpForbiddenException) {
|
||||
return $this->renderPage($response->withStatus(403), 'errors/403', [
|
||||
'exception' => $exception
|
||||
]);
|
||||
}
|
||||
|
||||
return $this->renderPage($response->withStatus(500), 'errors/500', [
|
||||
'exception' => $exception
|
||||
]);
|
||||
return $this->renderPage($response->withStatus(500), 'errors/500', [
|
||||
'exception' => $exception
|
||||
]);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,9 +16,9 @@ class FilesApiController extends BaseApiController
|
||||
{
|
||||
try
|
||||
{
|
||||
User::checkPermission($request, User::PERMISSION_UPLOAD_FILE);
|
||||
User::checkPermission($request, User::PERMISSION_UPLOAD_FILE);
|
||||
|
||||
if (IsValidFileName(base64_decode($args['fileName'])))
|
||||
if (IsValidFileName(base64_decode($args['fileName'])))
|
||||
{
|
||||
$fileName = base64_decode($args['fileName']);
|
||||
}
|
||||
@ -100,9 +100,9 @@ class FilesApiController extends BaseApiController
|
||||
{
|
||||
try
|
||||
{
|
||||
User::checkPermission($request, User::PERMISSION_DELETE_FILE);
|
||||
User::checkPermission($request, User::PERMISSION_DELETE_FILE);
|
||||
|
||||
if (IsValidFileName(base64_decode($args['fileName'])))
|
||||
if (IsValidFileName(base64_decode($args['fileName'])))
|
||||
{
|
||||
$fileName = base64_decode($args['fileName']);
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ class GenericEntityApiController extends BaseApiController
|
||||
|
||||
public function GetObjects(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
||||
{
|
||||
$objects = $this->getDatabase()->{$args['entity']}();
|
||||
$objects = $this->getDatabase()->{$args['entity']}();
|
||||
$allUserfields = $this->getUserfieldsService()->GetAllValues($args['entity']);
|
||||
|
||||
foreach ($objects as $object)
|
||||
@ -43,7 +43,7 @@ class GenericEntityApiController extends BaseApiController
|
||||
|
||||
public function GetObject(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
||||
{
|
||||
if ($this->IsValidEntity($args['entity']) && !$this->IsEntityWithPreventedListing($args['entity']))
|
||||
if ($this->IsValidEntity($args['entity']) && !$this->IsEntityWithPreventedListing($args['entity']))
|
||||
{
|
||||
$userfields = $this->getUserfieldsService()->GetValues($args['entity'], $args['objectId']);
|
||||
if (count($userfields) === 0)
|
||||
@ -52,9 +52,9 @@ class GenericEntityApiController extends BaseApiController
|
||||
}
|
||||
|
||||
$object = $this->getDatabase()->{$args['entity']}($args['objectId']);
|
||||
if ($object == null) {
|
||||
return $this->GenericErrorResponse($response, 'Object not found', 404);
|
||||
}
|
||||
if ($object == null) {
|
||||
return $this->GenericErrorResponse($response, 'Object not found', 404);
|
||||
}
|
||||
|
||||
$object['userfields'] = $userfields;
|
||||
|
||||
@ -68,9 +68,9 @@ class GenericEntityApiController extends BaseApiController
|
||||
|
||||
public function AddObject(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
||||
{
|
||||
User::checkPermission($request, User::PERMISSION_MASTER_DATA_EDIT);
|
||||
User::checkPermission($request, User::PERMISSION_MASTER_DATA_EDIT);
|
||||
|
||||
if ($this->IsValidEntity($args['entity']))
|
||||
if ($this->IsValidEntity($args['entity']))
|
||||
{
|
||||
$requestBody = $request->getParsedBody();
|
||||
|
||||
@ -101,9 +101,9 @@ class GenericEntityApiController extends BaseApiController
|
||||
|
||||
public function EditObject(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
||||
{
|
||||
User::checkPermission($request, User::PERMISSION_MASTER_DATA_EDIT);
|
||||
User::checkPermission($request, User::PERMISSION_MASTER_DATA_EDIT);
|
||||
|
||||
if ($this->IsValidEntity($args['entity']))
|
||||
if ($this->IsValidEntity($args['entity']))
|
||||
{
|
||||
$requestBody = $request->getParsedBody();
|
||||
|
||||
@ -132,9 +132,9 @@ class GenericEntityApiController extends BaseApiController
|
||||
|
||||
public function DeleteObject(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
||||
{
|
||||
User::checkPermission($request, User::PERMISSION_MASTER_DATA_EDIT);
|
||||
User::checkPermission($request, User::PERMISSION_MASTER_DATA_EDIT);
|
||||
|
||||
if ($this->IsValidEntity($args['entity']))
|
||||
if ($this->IsValidEntity($args['entity']))
|
||||
{
|
||||
$row = $this->getDatabase()->{$args['entity']}($args['objectId']);
|
||||
$row->delete();
|
||||
@ -150,7 +150,7 @@ class GenericEntityApiController extends BaseApiController
|
||||
public function SearchObjects(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
||||
{
|
||||
|
||||
if ($this->IsValidEntity($args['entity']) && !$this->IsEntityWithPreventedListing($args['entity']))
|
||||
if ($this->IsValidEntity($args['entity']) && !$this->IsEntityWithPreventedListing($args['entity']))
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -169,7 +169,7 @@ class GenericEntityApiController extends BaseApiController
|
||||
|
||||
public function GetUserfields(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
||||
{
|
||||
try
|
||||
try
|
||||
{
|
||||
return $this->ApiResponse($response, $this->getUserfieldsService()->GetValues($args['entity'], $args['objectId']));
|
||||
}
|
||||
@ -181,9 +181,9 @@ class GenericEntityApiController extends BaseApiController
|
||||
|
||||
public function SetUserfields(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
||||
{
|
||||
User::checkPermission($request, User::PERMISSION_MASTER_DATA_EDIT);
|
||||
User::checkPermission($request, User::PERMISSION_MASTER_DATA_EDIT);
|
||||
|
||||
$requestBody = $request->getParsedBody();
|
||||
$requestBody = $request->getParsedBody();
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -13,9 +13,9 @@ class RecipesApiController extends BaseApiController
|
||||
|
||||
public function AddNotFulfilledProductsToShoppingList(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
||||
{
|
||||
User::checkPermission($request, User::PERMISSION_SHOPPINGLIST_ITEMS_ADD);
|
||||
User::checkPermission($request, User::PERMISSION_SHOPPINGLIST_ITEMS_ADD);
|
||||
|
||||
$requestBody = $request->getParsedBody();
|
||||
$requestBody = $request->getParsedBody();
|
||||
$excludedProductIds = null;
|
||||
|
||||
if ($requestBody !== null && array_key_exists('excludedProductIds', $requestBody))
|
||||
@ -29,9 +29,9 @@ class RecipesApiController extends BaseApiController
|
||||
|
||||
public function ConsumeRecipe(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
||||
{
|
||||
User::checkPermission($request, User::PERMISSION_PRODUCT_CONSUME);
|
||||
User::checkPermission($request, User::PERMISSION_PRODUCT_CONSUME);
|
||||
|
||||
try
|
||||
try
|
||||
{
|
||||
$this->getRecipesService()->ConsumeRecipe($args['recipeId']);
|
||||
return $this->EmptyApiResponse($response);
|
||||
|
@ -51,7 +51,7 @@ class RecipesController extends BaseController
|
||||
if ($selectedRecipe)
|
||||
{
|
||||
$selectedRecipeSubRecipes = $this->getDatabase()->recipes()->where('id IN (SELECT includes_recipe_id FROM recipes_nestings_resolved WHERE recipe_id = :1 AND includes_recipe_id != :1)', $selectedRecipe->id)->orderBy('name')->fetchAll();
|
||||
|
||||
|
||||
$includedRecipeIdsAbsolute = array();
|
||||
$includedRecipeIdsAbsolute[] = $selectedRecipe->id;
|
||||
foreach($selectedRecipeSubRecipes as $subRecipe)
|
||||
|
@ -63,9 +63,9 @@ class StockApiController extends BaseApiController
|
||||
|
||||
public function AddProduct(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
||||
{
|
||||
User::checkPermission($request, User::PERMISSION_PRODUCT_PURCHASE);
|
||||
User::checkPermission($request, User::PERMISSION_PRODUCT_PURCHASE);
|
||||
|
||||
$requestBody = $request->getParsedBody();
|
||||
$requestBody = $request->getParsedBody();
|
||||
|
||||
try
|
||||
{
|
||||
@ -139,9 +139,9 @@ class StockApiController extends BaseApiController
|
||||
|
||||
public function EditStockEntry(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
||||
{
|
||||
User::checkPermission($request, User::PERMISSION_STOCK_EDIT);
|
||||
User::checkPermission($request, User::PERMISSION_STOCK_EDIT);
|
||||
|
||||
$requestBody = $request->getParsedBody();
|
||||
$requestBody = $request->getParsedBody();
|
||||
|
||||
try
|
||||
{
|
||||
@ -190,9 +190,9 @@ class StockApiController extends BaseApiController
|
||||
|
||||
public function TransferProduct(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
||||
{
|
||||
User::checkPermission($request, User::PERMISSION_STOCK_TRANSFER);
|
||||
User::checkPermission($request, User::PERMISSION_STOCK_TRANSFER);
|
||||
|
||||
$requestBody = $request->getParsedBody();
|
||||
$requestBody = $request->getParsedBody();
|
||||
|
||||
try
|
||||
{
|
||||
@ -246,9 +246,9 @@ class StockApiController extends BaseApiController
|
||||
|
||||
public function ConsumeProduct(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
||||
{
|
||||
User::checkPermission($request, User::PERMISSION_PRODUCT_CONSUME);
|
||||
User::checkPermission($request, User::PERMISSION_PRODUCT_CONSUME);
|
||||
|
||||
$requestBody = $request->getParsedBody();
|
||||
$requestBody = $request->getParsedBody();
|
||||
|
||||
$result = null;
|
||||
|
||||
@ -319,9 +319,9 @@ class StockApiController extends BaseApiController
|
||||
|
||||
public function InventoryProduct(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
||||
{
|
||||
User::checkPermission($request, User::PERMISSION_STOCK_CORRECTION);
|
||||
User::checkPermission($request, User::PERMISSION_STOCK_CORRECTION);
|
||||
|
||||
$requestBody = $request->getParsedBody();
|
||||
$requestBody = $request->getParsedBody();
|
||||
|
||||
try
|
||||
{
|
||||
@ -383,9 +383,9 @@ class StockApiController extends BaseApiController
|
||||
|
||||
public function OpenProduct(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
||||
{
|
||||
User::checkPermission($request, User::PERMISSION_PRODUCT_OPEN);
|
||||
User::checkPermission($request, User::PERMISSION_PRODUCT_OPEN);
|
||||
|
||||
$requestBody = $request->getParsedBody();
|
||||
$requestBody = $request->getParsedBody();
|
||||
|
||||
try
|
||||
{
|
||||
@ -452,9 +452,9 @@ class StockApiController extends BaseApiController
|
||||
|
||||
public function AddMissingProductsToShoppingList(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
||||
{
|
||||
User::checkPermission($request, User::PERMISSION_SHOPPINGLIST_ITEMS_ADD);
|
||||
User::checkPermission($request, User::PERMISSION_SHOPPINGLIST_ITEMS_ADD);
|
||||
|
||||
try
|
||||
try
|
||||
{
|
||||
$requestBody = $request->getParsedBody();
|
||||
|
||||
@ -475,9 +475,9 @@ class StockApiController extends BaseApiController
|
||||
|
||||
public function ClearShoppingList(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
||||
{
|
||||
User::checkPermission($request, User::PERMISSION_SHOPPINGLIST_ITEMS_DELETE);
|
||||
User::checkPermission($request, User::PERMISSION_SHOPPINGLIST_ITEMS_DELETE);
|
||||
|
||||
try
|
||||
try
|
||||
{
|
||||
$requestBody = $request->getParsedBody();
|
||||
|
||||
@ -499,9 +499,9 @@ class StockApiController extends BaseApiController
|
||||
|
||||
public function AddProductToShoppingList(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
||||
{
|
||||
User::checkPermission($request, User::PERMISSION_SHOPPINGLIST_ITEMS_ADD);
|
||||
User::checkPermission($request, User::PERMISSION_SHOPPINGLIST_ITEMS_ADD);
|
||||
|
||||
try
|
||||
try
|
||||
{
|
||||
$requestBody = $request->getParsedBody();
|
||||
|
||||
@ -542,9 +542,9 @@ class StockApiController extends BaseApiController
|
||||
|
||||
public function RemoveProductFromShoppingList(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
||||
{
|
||||
User::checkPermission($request, User::PERMISSION_SHOPPINGLIST_ITEMS_DELETE);
|
||||
User::checkPermission($request, User::PERMISSION_SHOPPINGLIST_ITEMS_DELETE);
|
||||
|
||||
try
|
||||
try
|
||||
{
|
||||
$requestBody = $request->getParsedBody();
|
||||
|
||||
@ -580,16 +580,16 @@ class StockApiController extends BaseApiController
|
||||
|
||||
public function ExternalBarcodeLookup(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
||||
{
|
||||
User::checkPermission($request, User::PERMISSION_MASTER_DATA_EDIT);
|
||||
User::checkPermission($request, User::PERMISSION_MASTER_DATA_EDIT);
|
||||
|
||||
try
|
||||
try
|
||||
{
|
||||
$addFoundProduct = false;
|
||||
if (isset($request->getQueryParams()['add']) && ($request->getQueryParams()['add'] === 'true' || $request->getQueryParams()['add'] === 1))
|
||||
{
|
||||
$addFoundProduct = true;
|
||||
}
|
||||
|
||||
|
||||
return $this->ApiResponse($response, $this->getStockService()->ExternalBarcodeLookup($args['barcode'], $addFoundProduct));
|
||||
}
|
||||
catch (\Exception $ex)
|
||||
@ -600,9 +600,9 @@ class StockApiController extends BaseApiController
|
||||
|
||||
public function UndoBooking(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
||||
{
|
||||
User::checkPermission($request, User::PERMISSION_STOCK_CORRECTION);
|
||||
User::checkPermission($request, User::PERMISSION_STOCK_CORRECTION);
|
||||
|
||||
try
|
||||
try
|
||||
{
|
||||
$this->ApiResponse($response, $this->getStockService()->UndoBooking($args['bookingId']));
|
||||
return $this->EmptyApiResponse($response);
|
||||
@ -615,9 +615,9 @@ class StockApiController extends BaseApiController
|
||||
|
||||
public function UndoTransaction(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
||||
{
|
||||
User::checkPermission($request, User::PERMISSION_STOCK_CORRECTION);
|
||||
User::checkPermission($request, User::PERMISSION_STOCK_CORRECTION);
|
||||
|
||||
try
|
||||
try
|
||||
{
|
||||
$this->ApiResponse($response, $this->getStockService()->UndoTransaction($args['transactionId']));
|
||||
return $this->EmptyApiResponse($response);
|
||||
@ -659,7 +659,7 @@ class StockApiController extends BaseApiController
|
||||
{
|
||||
throw new \Exception('Stock booking does not exist');
|
||||
}
|
||||
|
||||
|
||||
return $this->ApiResponse($response, $stockLogRow);
|
||||
}
|
||||
catch (\Exception $ex)
|
||||
@ -678,7 +678,7 @@ class StockApiController extends BaseApiController
|
||||
{
|
||||
throw new \Exception('No transaction was found by the given transaction id');
|
||||
}
|
||||
|
||||
|
||||
return $this->ApiResponse($response, $transactionRows);
|
||||
}
|
||||
catch (\Exception $ex)
|
||||
|
@ -16,7 +16,7 @@ class StockController extends BaseController
|
||||
$nextXDays = $usersService->GetUserSettings(GROCY_USER_ID)['stock_expring_soon_days'];
|
||||
|
||||
return $this->renderPage($response, 'stockoverview', [
|
||||
'currentStock' => $this->getStockService()->GetCurrentStockOverview(),
|
||||
'currentStock' => $this->getStockService()->GetCurrentStockOverview(),
|
||||
'locations' => $this->getDatabase()->locations()->orderBy('name'),
|
||||
'currentStockLocations' => $this->getStockService()->GetCurrentStockLocations(),
|
||||
'nextXDays' => $nextXDays,
|
||||
|
@ -11,9 +11,9 @@ class SystemApiController extends BaseApiController
|
||||
|
||||
public function GetDbChangedTime(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
||||
{
|
||||
return $this->ApiResponse($response, array(
|
||||
'changed_time' => $this->getDatabaseService()->GetDbChangedTime()
|
||||
));
|
||||
return $this->ApiResponse($response, array(
|
||||
'changed_time' => $this->getDatabaseService()->GetDbChangedTime()
|
||||
));
|
||||
}
|
||||
|
||||
public function GetConfig(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
||||
|
@ -18,9 +18,9 @@ class TasksApiController extends BaseApiController
|
||||
|
||||
public function MarkTaskAsCompleted(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
||||
{
|
||||
User::checkPermission($request, User::PERMISSION_TASKS_MARK_COMPLETED);
|
||||
User::checkPermission($request, User::PERMISSION_TASKS_MARK_COMPLETED);
|
||||
|
||||
$requestBody = $request->getParsedBody();
|
||||
$requestBody = $request->getParsedBody();
|
||||
|
||||
try
|
||||
{
|
||||
@ -41,9 +41,9 @@ class TasksApiController extends BaseApiController
|
||||
|
||||
public function UndoTask(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
||||
{
|
||||
User::checkPermission($request, User::PERMISSION_TASKS_UNDO);
|
||||
User::checkPermission($request, User::PERMISSION_TASKS_UNDO);
|
||||
|
||||
try
|
||||
try
|
||||
{
|
||||
$this->getTasksService()->UndoTask($args['taskId']);
|
||||
return $this->EmptyApiResponse($response);
|
||||
|
@ -8,8 +8,8 @@ use Throwable;
|
||||
|
||||
class PermissionMissingException extends HttpForbiddenException
|
||||
{
|
||||
public function __construct(ServerRequestInterface $request, string $permission, ?Throwable $previous = null)
|
||||
{
|
||||
parent::__construct($request, 'Permission missing: ' . $permission, $previous);
|
||||
}
|
||||
}
|
||||
public function __construct(ServerRequestInterface $request, string $permission, ?Throwable $previous = null)
|
||||
{
|
||||
parent::__construct($request, 'Permission missing: ' . $permission, $previous);
|
||||
}
|
||||
}
|
||||
|
@ -7,85 +7,85 @@ use LessQL\Result;
|
||||
|
||||
class User
|
||||
{
|
||||
const PERMISSION_ADMIN = 'ADMIN';
|
||||
const PERMISSION_CREATE_USER = 'CREATE_USER';
|
||||
const PERMISSION_EDIT_USER = 'EDIT_USER';
|
||||
const PERMISSION_READ_USER = 'READ_USER';
|
||||
const PERMISSION_EDIT_SELF = 'EDIT_SELF';
|
||||
const PERMISSION_BATTERY_UNDO_TRACK_CHARGE_CYCLE = 'BATTERY_UNDO_TRACK_CHARGE_CYCLE';
|
||||
const PERMISSION_BATTERY_TRACK_CHARGE_CYCLE = 'BATTERY_TRACK_CHARGE_CYCLE';
|
||||
const PERMISSION_CHORE_TRACK = 'CHORE_TRACK';
|
||||
const PERMISSION_CHORE_TRACK_OTHERS = 'CHORE_TRACK_OTHERS';
|
||||
const PERMISSION_CHORE_EDIT = 'CHORE_EDIT';
|
||||
const PERMISSION_CHORE_UNDO = 'CHORE_UNDO';
|
||||
const PERMISSION_UPLOAD_FILE = 'UPLOAD_FILE';
|
||||
const PERMISSION_DELETE_FILE = 'DELETE_FILE';
|
||||
const PERMISSION_MASTER_DATA_EDIT = 'MASTER_DATA_EDIT';
|
||||
const PERMISSION_TASKS_UNDO = 'TASKS_UNDO';
|
||||
const PERMISSION_TASKS_MARK_COMPLETED = 'TASKS_MARK_COMPLETED';
|
||||
const PERMISSION_STOCK_TRANSFER = 'STOCK_TRANSFER';
|
||||
const PERMISSION_STOCK_EDIT = 'STOCK_EDIT';
|
||||
const PERMISSION_PRODUCT_CONSUME = 'PRODUCT_CONSUME';
|
||||
const PERMISSION_STOCK_CORRECTION = 'STOCK_CORRECTION';
|
||||
const PERMISSION_PRODUCT_OPEN = 'PRODUCT_OPEN';
|
||||
const PERMISSION_SHOPPINGLIST_ITEMS_ADD = 'SHOPPINGLIST_ITEMS_ADD';
|
||||
const PERMISSION_SHOPPINGLIST_ITEMS_DELETE = 'SHOPPINGLIST_ITEMS_DELETE';
|
||||
const PERMISSION_PRODUCT_PURCHASE = 'PRODUCT_PURCHASE';
|
||||
const PERMISSION_ADMIN = 'ADMIN';
|
||||
const PERMISSION_CREATE_USER = 'CREATE_USER';
|
||||
const PERMISSION_EDIT_USER = 'EDIT_USER';
|
||||
const PERMISSION_READ_USER = 'READ_USER';
|
||||
const PERMISSION_EDIT_SELF = 'EDIT_SELF';
|
||||
const PERMISSION_BATTERY_UNDO_TRACK_CHARGE_CYCLE = 'BATTERY_UNDO_TRACK_CHARGE_CYCLE';
|
||||
const PERMISSION_BATTERY_TRACK_CHARGE_CYCLE = 'BATTERY_TRACK_CHARGE_CYCLE';
|
||||
const PERMISSION_CHORE_TRACK = 'CHORE_TRACK';
|
||||
const PERMISSION_CHORE_TRACK_OTHERS = 'CHORE_TRACK_OTHERS';
|
||||
const PERMISSION_CHORE_EDIT = 'CHORE_EDIT';
|
||||
const PERMISSION_CHORE_UNDO = 'CHORE_UNDO';
|
||||
const PERMISSION_UPLOAD_FILE = 'UPLOAD_FILE';
|
||||
const PERMISSION_DELETE_FILE = 'DELETE_FILE';
|
||||
const PERMISSION_MASTER_DATA_EDIT = 'MASTER_DATA_EDIT';
|
||||
const PERMISSION_TASKS_UNDO = 'TASKS_UNDO';
|
||||
const PERMISSION_TASKS_MARK_COMPLETED = 'TASKS_MARK_COMPLETED';
|
||||
const PERMISSION_STOCK_TRANSFER = 'STOCK_TRANSFER';
|
||||
const PERMISSION_STOCK_EDIT = 'STOCK_EDIT';
|
||||
const PERMISSION_PRODUCT_CONSUME = 'PRODUCT_CONSUME';
|
||||
const PERMISSION_STOCK_CORRECTION = 'STOCK_CORRECTION';
|
||||
const PERMISSION_PRODUCT_OPEN = 'PRODUCT_OPEN';
|
||||
const PERMISSION_SHOPPINGLIST_ITEMS_ADD = 'SHOPPINGLIST_ITEMS_ADD';
|
||||
const PERMISSION_SHOPPINGLIST_ITEMS_DELETE = 'SHOPPINGLIST_ITEMS_DELETE';
|
||||
const PERMISSION_PRODUCT_PURCHASE = 'PRODUCT_PURCHASE';
|
||||
|
||||
/**
|
||||
* @var \LessQL\Database|null
|
||||
*/
|
||||
protected $db;
|
||||
/**
|
||||
* @var \LessQL\Database|null
|
||||
*/
|
||||
protected $db;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->db = DatabaseService::getInstance()->GetDbConnection();
|
||||
public function __construct()
|
||||
{
|
||||
$this->db = DatabaseService::getInstance()->GetDbConnection();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
protected function getPermissions(): Result
|
||||
{
|
||||
return $this->db->user_permissions_resolved()->where('user_id', GROCY_USER_ID);
|
||||
}
|
||||
protected function getPermissions(): Result
|
||||
{
|
||||
return $this->db->user_permissions_resolved()->where('user_id', GROCY_USER_ID);
|
||||
}
|
||||
|
||||
public function hasPermission(string $permission): bool
|
||||
{
|
||||
// global $PERMISSION_CACHE;
|
||||
// if(isset($PERMISSION_CACHE[$permission]))
|
||||
// return $PERMISSION_CACHE[$permission];
|
||||
return $this->getPermissions()->where('permission_name', $permission)->fetch() !== null;
|
||||
}
|
||||
public function hasPermission(string $permission): bool
|
||||
{
|
||||
// global $PERMISSION_CACHE;
|
||||
// if(isset($PERMISSION_CACHE[$permission]))
|
||||
// return $PERMISSION_CACHE[$permission];
|
||||
return $this->getPermissions()->where('permission_name', $permission)->fetch() !== null;
|
||||
}
|
||||
|
||||
public static function checkPermission($request, string ...$permissions): void
|
||||
{
|
||||
$user = new User();
|
||||
foreach ($permissions as $permission) {
|
||||
if (!$user->hasPermission($permission)) {
|
||||
throw new PermissionMissingException($request, $permission);
|
||||
}
|
||||
}
|
||||
public static function checkPermission($request, string ...$permissions): void
|
||||
{
|
||||
$user = new User();
|
||||
foreach ($permissions as $permission) {
|
||||
if (!$user->hasPermission($permission)) {
|
||||
throw new PermissionMissingException($request, $permission);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public function getPermissionList()
|
||||
{
|
||||
return $this->db->uihelper_user_permissions()->where('user_id', GROCY_USER_ID);
|
||||
}
|
||||
public function getPermissionList()
|
||||
{
|
||||
return $this->db->uihelper_user_permissions()->where('user_id', GROCY_USER_ID);
|
||||
}
|
||||
|
||||
public static function hasPermissions(string ...$permissions)
|
||||
{
|
||||
$user = new User();
|
||||
foreach ($permissions as $permission) {
|
||||
if (!$user->hasPermission($permission)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public static function hasPermissions(string ...$permissions)
|
||||
{
|
||||
$user = new User();
|
||||
foreach ($permissions as $permission) {
|
||||
if (!$user->hasPermission($permission)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function PermissionList()
|
||||
{
|
||||
$user = new User();
|
||||
return $user->getPermissionList();
|
||||
}
|
||||
public static function PermissionList()
|
||||
{
|
||||
$user = new User();
|
||||
return $user->getPermissionList();
|
||||
}
|
||||
}
|
||||
|
@ -13,8 +13,8 @@ class UsersApiController extends BaseApiController
|
||||
|
||||
public function GetUsers(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
||||
{
|
||||
User::checkPermission($request, User::PERMISSION_READ_USER);
|
||||
try
|
||||
User::checkPermission($request, User::PERMISSION_READ_USER);
|
||||
try
|
||||
{
|
||||
return $this->ApiResponse($response, $this->getUsersService()->GetUsersAsDto());
|
||||
}
|
||||
@ -26,7 +26,7 @@ class UsersApiController extends BaseApiController
|
||||
|
||||
public function CreateUser(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
||||
{
|
||||
User::checkPermission($request, User::PERMISSION_CREATE_USER);
|
||||
User::checkPermission($request, User::PERMISSION_CREATE_USER);
|
||||
$requestBody = $request->getParsedBody();
|
||||
|
||||
try
|
||||
@ -47,8 +47,8 @@ class UsersApiController extends BaseApiController
|
||||
|
||||
public function DeleteUser(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
||||
{
|
||||
User::checkPermission($request, User::PERMISSION_EDIT_USER);
|
||||
try
|
||||
User::checkPermission($request, User::PERMISSION_EDIT_USER);
|
||||
try
|
||||
{
|
||||
$this->getUsersService()->DeleteUser($args['userId']);
|
||||
return $this->EmptyApiResponse($response);
|
||||
@ -61,12 +61,12 @@ class UsersApiController extends BaseApiController
|
||||
|
||||
public function EditUser(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
||||
{
|
||||
if ($args['userId'] == GROCY_USER_ID) {
|
||||
User::checkPermission($request, User::PERMISSION_EDIT_SELF);
|
||||
} else {
|
||||
User::checkPermission($request, User::PERMISSION_EDIT_USER);
|
||||
}
|
||||
$requestBody = $request->getParsedBody();
|
||||
if ($args['userId'] == GROCY_USER_ID) {
|
||||
User::checkPermission($request, User::PERMISSION_EDIT_SELF);
|
||||
} else {
|
||||
User::checkPermission($request, User::PERMISSION_EDIT_USER);
|
||||
}
|
||||
$requestBody = $request->getParsedBody();
|
||||
|
||||
try
|
||||
{
|
||||
@ -119,65 +119,65 @@ class UsersApiController extends BaseApiController
|
||||
}
|
||||
}
|
||||
|
||||
public function AddPermission(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
||||
{
|
||||
try {
|
||||
User::checkPermission($request, User::PERMISSION_ADMIN);
|
||||
$requestBody = $request->getParsedBody();
|
||||
public function AddPermission(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
||||
{
|
||||
try {
|
||||
User::checkPermission($request, User::PERMISSION_ADMIN);
|
||||
$requestBody = $request->getParsedBody();
|
||||
|
||||
$this->getDatabase()->user_permissions()->createRow(array(
|
||||
'user_id' => $args['userId'],
|
||||
'permission_id' => $requestBody['permission_id'],
|
||||
))->save();
|
||||
return $this->EmptyApiResponse($response);
|
||||
} catch (\Slim\Exception\HttpSpecializedException $ex) {
|
||||
return $this->GenericErrorResponse($response, $ex->getMessage(), $ex->getCode());
|
||||
} catch (\Exception $ex) {
|
||||
return $this->GenericErrorResponse($response, $ex->getMessage());
|
||||
}
|
||||
}
|
||||
$this->getDatabase()->user_permissions()->createRow(array(
|
||||
'user_id' => $args['userId'],
|
||||
'permission_id' => $requestBody['permission_id'],
|
||||
))->save();
|
||||
return $this->EmptyApiResponse($response);
|
||||
} catch (\Slim\Exception\HttpSpecializedException $ex) {
|
||||
return $this->GenericErrorResponse($response, $ex->getMessage(), $ex->getCode());
|
||||
} catch (\Exception $ex) {
|
||||
return $this->GenericErrorResponse($response, $ex->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function ListPermissions(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
||||
{
|
||||
try {
|
||||
User::checkPermission($request, User::PERMISSION_ADMIN);
|
||||
public function ListPermissions(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
||||
{
|
||||
try {
|
||||
User::checkPermission($request, User::PERMISSION_ADMIN);
|
||||
|
||||
return $this->ApiResponse($response,
|
||||
$this->getDatabase()->user_permissions()->where($args['userId'])
|
||||
);
|
||||
} catch (\Slim\Exception\HttpSpecializedException $ex) {
|
||||
return $this->GenericErrorResponse($response, $ex->getMessage(), $ex->getCode());
|
||||
} catch (\Exception $ex) {
|
||||
return $this->GenericErrorResponse($response, $ex->getMessage());
|
||||
}
|
||||
}
|
||||
return $this->ApiResponse($response,
|
||||
$this->getDatabase()->user_permissions()->where($args['userId'])
|
||||
);
|
||||
} catch (\Slim\Exception\HttpSpecializedException $ex) {
|
||||
return $this->GenericErrorResponse($response, $ex->getMessage(), $ex->getCode());
|
||||
} catch (\Exception $ex) {
|
||||
return $this->GenericErrorResponse($response, $ex->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function SetPermissions(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
||||
{
|
||||
try {
|
||||
User::checkPermission($request, User::PERMISSION_ADMIN);
|
||||
$requestBody = $request->getParsedBody();
|
||||
$db = $this->getDatabase();
|
||||
$db->user_permissions()
|
||||
->where('user_id', $args['userId'])
|
||||
->delete();
|
||||
public function SetPermissions(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
||||
{
|
||||
try {
|
||||
User::checkPermission($request, User::PERMISSION_ADMIN);
|
||||
$requestBody = $request->getParsedBody();
|
||||
$db = $this->getDatabase();
|
||||
$db->user_permissions()
|
||||
->where('user_id', $args['userId'])
|
||||
->delete();
|
||||
|
||||
$perms = [];
|
||||
$perms = [];
|
||||
|
||||
foreach ($requestBody['permissions'] as $perm_id) {
|
||||
$perms[] = array(
|
||||
'user_id' => $args['userId'],
|
||||
'permission_id' => $perm_id
|
||||
);
|
||||
}
|
||||
foreach ($requestBody['permissions'] as $perm_id) {
|
||||
$perms[] = array(
|
||||
'user_id' => $args['userId'],
|
||||
'permission_id' => $perm_id
|
||||
);
|
||||
}
|
||||
|
||||
$db->insert('user_permissions', $perms, 'batch');
|
||||
$db->insert('user_permissions', $perms, 'batch');
|
||||
|
||||
return $this->EmptyApiResponse($response);
|
||||
} catch (\Slim\Exception\HttpSpecializedException $ex) {
|
||||
return $this->GenericErrorResponse($response, $ex->getMessage(), $ex->getCode());
|
||||
} catch (\Exception $ex) {
|
||||
return $this->GenericErrorResponse($response, $ex->getMessage());
|
||||
}
|
||||
}
|
||||
return $this->EmptyApiResponse($response);
|
||||
} catch (\Slim\Exception\HttpSpecializedException $ex) {
|
||||
return $this->GenericErrorResponse($response, $ex->getMessage(), $ex->getCode());
|
||||
} catch (\Exception $ex) {
|
||||
return $this->GenericErrorResponse($response, $ex->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,8 +8,8 @@ class UsersController extends BaseController
|
||||
{
|
||||
public function UsersList(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
||||
{
|
||||
User::checkPermission($request, User::PERMISSION_READ_USER);
|
||||
return $this->renderPage($response, 'users', [
|
||||
User::checkPermission($request, User::PERMISSION_READ_USER);
|
||||
return $this->renderPage($response, 'users', [
|
||||
'users' => $this->getDatabase()->users()->orderBy('username')
|
||||
]);
|
||||
}
|
||||
@ -18,30 +18,30 @@ class UsersController extends BaseController
|
||||
{
|
||||
if ($args['userId'] == 'new')
|
||||
{
|
||||
User::checkPermission($request, User::PERMISSION_CREATE_USER);
|
||||
return $this->renderPage($response, 'userform', [
|
||||
User::checkPermission($request, User::PERMISSION_CREATE_USER);
|
||||
return $this->renderPage($response, 'userform', [
|
||||
'mode' => 'create'
|
||||
]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if($args['userId'] == GROCY_USER_ID)
|
||||
User::checkPermission($request, User::PERMISSION_EDIT_SELF);
|
||||
else User::checkPermission($request, User::PERMISSION_EDIT_USER);
|
||||
return $this->renderPage($response, 'userform', [
|
||||
if($args['userId'] == GROCY_USER_ID)
|
||||
User::checkPermission($request, User::PERMISSION_EDIT_SELF);
|
||||
else User::checkPermission($request, User::PERMISSION_EDIT_USER);
|
||||
return $this->renderPage($response, 'userform', [
|
||||
'user' => $this->getDatabase()->users($args['userId']),
|
||||
'mode' => 'edit'
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
public function PermissionList(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
||||
{
|
||||
User::checkPermission($request, User::PERMISSION_READ_USER);
|
||||
return $this->renderPage($response, 'userpermissions', [
|
||||
'user' => $this->getDatabase()->users($args['userId']),
|
||||
'permissions' => $this->getDatabase()->uihelper_user_permissions()
|
||||
->where('parent IS NULL')->where('user_id', $args['userId']),
|
||||
]);
|
||||
}
|
||||
public function PermissionList(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
||||
{
|
||||
User::checkPermission($request, User::PERMISSION_READ_USER);
|
||||
return $this->renderPage($response, 'userpermissions', [
|
||||
'user' => $this->getDatabase()->users($args['userId']),
|
||||
'permissions' => $this->getDatabase()->uihelper_user_permissions()
|
||||
->where('parent IS NULL')->where('user_id', $args['userId']),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
@ -7,61 +7,61 @@ const REQUIRED_SQLITE_VERSION = "3.8.3";
|
||||
|
||||
class PrerequisiteChecker
|
||||
{
|
||||
public function checkRequirements()
|
||||
{
|
||||
self::checkForConfigFile();
|
||||
self::checkForConfigDistFile();
|
||||
self::checkForComposer();
|
||||
self::checkForPhpExtensions();
|
||||
self::checkForSqliteVersion();
|
||||
}
|
||||
|
||||
|
||||
private function checkForConfigFile()
|
||||
{
|
||||
if (!file_exists(GROCY_DATAPATH . '/config.php'))
|
||||
{
|
||||
throw new ERequirementNotMet('config.php in data directory (' . GROCY_DATAPATH . ') not found. Have you copied config-dist.php to the data directory and renamed it to config.php?');
|
||||
}
|
||||
}
|
||||
|
||||
private function checkForConfigDistFile()
|
||||
{
|
||||
if (!file_exists(__DIR__ . '/../config-dist.php'))
|
||||
{
|
||||
throw new ERequirementNotMet('config-dist.php not found. Please do not remove this file.');
|
||||
}
|
||||
}
|
||||
|
||||
private function checkForComposer()
|
||||
{
|
||||
if (!file_exists(__DIR__ . '/../vendor/autoload.php'))
|
||||
{
|
||||
throw new ERequirementNotMet('/vendor/autoload.php not found. Have you run Composer?');
|
||||
}
|
||||
}
|
||||
|
||||
private function checkForPhpExtensions()
|
||||
{
|
||||
$loadedExtensions = get_loaded_extensions();
|
||||
foreach (REQUIRED_PHP_EXTENSIONS as $extension)
|
||||
{
|
||||
if (!in_array($extension, $loadedExtensions))
|
||||
{
|
||||
throw new ERequirementNotMet("PHP module '{$extension}' not installed, but required.");
|
||||
}
|
||||
}
|
||||
}
|
||||
public function checkRequirements()
|
||||
{
|
||||
self::checkForConfigFile();
|
||||
self::checkForConfigDistFile();
|
||||
self::checkForComposer();
|
||||
self::checkForPhpExtensions();
|
||||
self::checkForSqliteVersion();
|
||||
}
|
||||
|
||||
|
||||
private function checkForSqliteVersion()
|
||||
{
|
||||
$sqliteVersion = self::getSqlVersionAsString();
|
||||
if (version_compare($sqliteVersion, REQUIRED_SQLITE_VERSION, '<'))
|
||||
{
|
||||
throw new ERequirementNotMet('SQLite ' . REQUIRED_SQLITE_VERSION . ' is required, however you are running ' . $sqliteVersion);
|
||||
}
|
||||
}
|
||||
private function checkForConfigFile()
|
||||
{
|
||||
if (!file_exists(GROCY_DATAPATH . '/config.php'))
|
||||
{
|
||||
throw new ERequirementNotMet('config.php in data directory (' . GROCY_DATAPATH . ') not found. Have you copied config-dist.php to the data directory and renamed it to config.php?');
|
||||
}
|
||||
}
|
||||
|
||||
private function checkForConfigDistFile()
|
||||
{
|
||||
if (!file_exists(__DIR__ . '/../config-dist.php'))
|
||||
{
|
||||
throw new ERequirementNotMet('config-dist.php not found. Please do not remove this file.');
|
||||
}
|
||||
}
|
||||
|
||||
private function checkForComposer()
|
||||
{
|
||||
if (!file_exists(__DIR__ . '/../vendor/autoload.php'))
|
||||
{
|
||||
throw new ERequirementNotMet('/vendor/autoload.php not found. Have you run Composer?');
|
||||
}
|
||||
}
|
||||
|
||||
private function checkForPhpExtensions()
|
||||
{
|
||||
$loadedExtensions = get_loaded_extensions();
|
||||
foreach (REQUIRED_PHP_EXTENSIONS as $extension)
|
||||
{
|
||||
if (!in_array($extension, $loadedExtensions))
|
||||
{
|
||||
throw new ERequirementNotMet("PHP module '{$extension}' not installed, but required.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private function checkForSqliteVersion()
|
||||
{
|
||||
$sqliteVersion = self::getSqlVersionAsString();
|
||||
if (version_compare($sqliteVersion, REQUIRED_SQLITE_VERSION, '<'))
|
||||
{
|
||||
throw new ERequirementNotMet('SQLite ' . REQUIRED_SQLITE_VERSION . ' is required, however you are running ' . $sqliteVersion);
|
||||
}
|
||||
}
|
||||
|
||||
private function getSqlVersionAsString()
|
||||
{
|
||||
|
@ -82,4 +82,4 @@ msgid "SHOPPINGLIST_ITEMS_ADD"
|
||||
msgstr ""
|
||||
|
||||
msgid "SHOPPINGLIST_ITEMS_DELETE"
|
||||
msgstr ""
|
||||
msgstr ""
|
||||
|
@ -10,67 +10,67 @@ use Grocy\Services\ApiKeyService;
|
||||
|
||||
class ApiKeyAuthMiddleware extends AuthMiddleware
|
||||
{
|
||||
public function __construct(\DI\Container $container, ResponseFactoryInterface $responseFactory)
|
||||
{
|
||||
parent::__construct($container, $responseFactory);
|
||||
$this->ApiKeyHeaderName = $this->AppContainer->get('ApiKeyHeaderName');
|
||||
}
|
||||
public function __construct(\DI\Container $container, ResponseFactoryInterface $responseFactory)
|
||||
{
|
||||
parent::__construct($container, $responseFactory);
|
||||
$this->ApiKeyHeaderName = $this->AppContainer->get('ApiKeyHeaderName');
|
||||
}
|
||||
|
||||
protected $ApiKeyHeaderName;
|
||||
protected $ApiKeyHeaderName;
|
||||
|
||||
function authenticate(Request $request)
|
||||
{
|
||||
if (!defined('GROCY_SHOW_AUTH_VIEWS'))
|
||||
{
|
||||
define('GROCY_SHOW_AUTH_VIEWS', true);
|
||||
}
|
||||
function authenticate(Request $request)
|
||||
{
|
||||
if (!defined('GROCY_SHOW_AUTH_VIEWS'))
|
||||
{
|
||||
define('GROCY_SHOW_AUTH_VIEWS', true);
|
||||
}
|
||||
|
||||
$routeContext = RouteContext::fromRequest($request);
|
||||
$route = $routeContext->getRoute();
|
||||
$routeName = $route->getName();
|
||||
$routeContext = RouteContext::fromRequest($request);
|
||||
$route = $routeContext->getRoute();
|
||||
$routeName = $route->getName();
|
||||
|
||||
$validApiKey = true;
|
||||
$usedApiKey = null;
|
||||
$validApiKey = true;
|
||||
$usedApiKey = null;
|
||||
|
||||
$apiKeyService = new ApiKeyService();
|
||||
$apiKeyService = new ApiKeyService();
|
||||
|
||||
// First check of the API key in the configured header
|
||||
if (!$request->hasHeader($this->ApiKeyHeaderName) || !$apiKeyService->IsValidApiKey($request->getHeaderLine($this->ApiKeyHeaderName)))
|
||||
{
|
||||
$validApiKey = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
$usedApiKey = $request->getHeaderLine($this->ApiKeyHeaderName);
|
||||
}
|
||||
// First check of the API key in the configured header
|
||||
if (!$request->hasHeader($this->ApiKeyHeaderName) || !$apiKeyService->IsValidApiKey($request->getHeaderLine($this->ApiKeyHeaderName)))
|
||||
{
|
||||
$validApiKey = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
$usedApiKey = $request->getHeaderLine($this->ApiKeyHeaderName);
|
||||
}
|
||||
|
||||
// Not recommended, but it's also possible to provide the API key via a query parameter (same name as the configured header)
|
||||
if (!$validApiKey && !empty($request->getQueryParam($this->ApiKeyHeaderName)) && $apiKeyService->IsValidApiKey($request->getQueryParam($this->ApiKeyHeaderName)))
|
||||
{
|
||||
$validApiKey = true;
|
||||
$usedApiKey = $request->getQueryParam($this->ApiKeyHeaderName);
|
||||
}
|
||||
// Not recommended, but it's also possible to provide the API key via a query parameter (same name as the configured header)
|
||||
if (!$validApiKey && !empty($request->getQueryParam($this->ApiKeyHeaderName)) && $apiKeyService->IsValidApiKey($request->getQueryParam($this->ApiKeyHeaderName)))
|
||||
{
|
||||
$validApiKey = true;
|
||||
$usedApiKey = $request->getQueryParam($this->ApiKeyHeaderName);
|
||||
}
|
||||
|
||||
// Handling of special purpose API keys
|
||||
if (!$validApiKey)
|
||||
{
|
||||
if ($routeName === 'calendar-ical')
|
||||
{
|
||||
if ($request->getQueryParam('secret') !== null && $apiKeyService->IsValidApiKey($request->getQueryParam('secret'), ApiKeyService::API_KEY_TYPE_SPECIAL_PURPOSE_CALENDAR_ICAL))
|
||||
{
|
||||
$validApiKey = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Handling of special purpose API keys
|
||||
if (!$validApiKey)
|
||||
{
|
||||
if ($routeName === 'calendar-ical')
|
||||
{
|
||||
if ($request->getQueryParam('secret') !== null && $apiKeyService->IsValidApiKey($request->getQueryParam('secret'), ApiKeyService::API_KEY_TYPE_SPECIAL_PURPOSE_CALENDAR_ICAL))
|
||||
{
|
||||
$validApiKey = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($validApiKey)
|
||||
{
|
||||
return $apiKeyService->GetUserByApiKey($usedApiKey);
|
||||
if ($validApiKey)
|
||||
{
|
||||
return $apiKeyService->GetUserByApiKey($usedApiKey);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,73 +12,73 @@ use Grocy\Services\SessionService;
|
||||
|
||||
abstract class AuthMiddleware extends BaseMiddleware
|
||||
{
|
||||
public function __construct(\DI\Container $container, ResponseFactoryInterface $responseFactory)
|
||||
{
|
||||
parent::__construct($container);
|
||||
$this->ResponseFactory = $responseFactory;
|
||||
}
|
||||
public function __construct(\DI\Container $container, ResponseFactoryInterface $responseFactory)
|
||||
{
|
||||
parent::__construct($container);
|
||||
$this->ResponseFactory = $responseFactory;
|
||||
}
|
||||
|
||||
protected $ResponseFactory;
|
||||
protected $ResponseFactory;
|
||||
|
||||
public function __invoke(Request $request, RequestHandler $handler): Response
|
||||
{
|
||||
$routeContext = RouteContext::fromRequest($request);
|
||||
$route = $routeContext->getRoute();
|
||||
$routeName = $route->getName();
|
||||
$isApiRoute = string_starts_with($request->getUri()->getPath(), '/api/');
|
||||
public function __invoke(Request $request, RequestHandler $handler): Response
|
||||
{
|
||||
$routeContext = RouteContext::fromRequest($request);
|
||||
$route = $routeContext->getRoute();
|
||||
$routeName = $route->getName();
|
||||
$isApiRoute = string_starts_with($request->getUri()->getPath(), '/api/');
|
||||
|
||||
if ($routeName === 'root')
|
||||
{
|
||||
return $handler->handle($request);
|
||||
}
|
||||
else if ($routeName === 'login')
|
||||
{
|
||||
define('GROCY_AUTHENTICATED', false);
|
||||
return $handler->handle($request);
|
||||
}
|
||||
if (GROCY_MODE === 'dev' || GROCY_MODE === 'demo' || GROCY_MODE === 'prerelease' || GROCY_IS_EMBEDDED_INSTALL || GROCY_DISABLE_AUTH)
|
||||
{
|
||||
$sessionService = SessionService::getInstance();
|
||||
$user = $sessionService->GetDefaultUser();
|
||||
if ($routeName === 'root')
|
||||
{
|
||||
return $handler->handle($request);
|
||||
}
|
||||
else if ($routeName === 'login')
|
||||
{
|
||||
define('GROCY_AUTHENTICATED', false);
|
||||
return $handler->handle($request);
|
||||
}
|
||||
if (GROCY_MODE === 'dev' || GROCY_MODE === 'demo' || GROCY_MODE === 'prerelease' || GROCY_IS_EMBEDDED_INSTALL || GROCY_DISABLE_AUTH)
|
||||
{
|
||||
$sessionService = SessionService::getInstance();
|
||||
$user = $sessionService->GetDefaultUser();
|
||||
|
||||
define('GROCY_AUTHENTICATED', true);
|
||||
define('GROCY_USER_USERNAME', $user->username);
|
||||
define('GROCY_AUTHENTICATED', true);
|
||||
define('GROCY_USER_USERNAME', $user->username);
|
||||
|
||||
return $handler->handle($request);
|
||||
}
|
||||
else
|
||||
{
|
||||
$user = $this->authenticate($request);
|
||||
return $handler->handle($request);
|
||||
}
|
||||
else
|
||||
{
|
||||
$user = $this->authenticate($request);
|
||||
|
||||
if ($user === null)
|
||||
{
|
||||
define('GROCY_AUTHENTICATED', false);
|
||||
if ($user === null)
|
||||
{
|
||||
define('GROCY_AUTHENTICATED', false);
|
||||
|
||||
$response = $this->ResponseFactory->createResponse();
|
||||
if ($isApiRoute)
|
||||
{
|
||||
return $response->withStatus(401);
|
||||
}
|
||||
else
|
||||
{
|
||||
return $response->withHeader('Location', $this->AppContainer->get('UrlManager')->ConstructUrl('/login'));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
define('GROCY_AUTHENTICATED', true);
|
||||
define('GROCY_USER_ID', $user->id);
|
||||
define('GROCY_USER_USERNAME', $user->username);
|
||||
$response = $this->ResponseFactory->createResponse();
|
||||
if ($isApiRoute)
|
||||
{
|
||||
return $response->withStatus(401);
|
||||
}
|
||||
else
|
||||
{
|
||||
return $response->withHeader('Location', $this->AppContainer->get('UrlManager')->ConstructUrl('/login'));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
define('GROCY_AUTHENTICATED', true);
|
||||
define('GROCY_USER_ID', $user->id);
|
||||
define('GROCY_USER_USERNAME', $user->username);
|
||||
|
||||
return $response = $handler->handle($request);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $response = $handler->handle($request);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @return mixed|null the user row or null if the request is not authenticated
|
||||
* @throws \Exception Throws an \Exception if config is invalid.
|
||||
*/
|
||||
protected abstract function authenticate(Request $request);
|
||||
/**
|
||||
* @param Request $request
|
||||
* @return mixed|null the user row or null if the request is not authenticated
|
||||
* @throws \Exception Throws an \Exception if config is invalid.
|
||||
*/
|
||||
protected abstract function authenticate(Request $request);
|
||||
}
|
||||
|
@ -6,19 +6,19 @@ use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
|
||||
class DefaultAuthMiddleware extends AuthMiddleware
|
||||
{
|
||||
protected function authenticate(Request $request)
|
||||
{
|
||||
// First try to authenticate by API key
|
||||
$auth = new ApiKeyAuthMiddleware($this->AppContainer, $this->ResponseFactory);
|
||||
$user = $auth->authenticate($request);
|
||||
if ($user !== null)
|
||||
{
|
||||
return $user;
|
||||
}
|
||||
protected function authenticate(Request $request)
|
||||
{
|
||||
// First try to authenticate by API key
|
||||
$auth = new ApiKeyAuthMiddleware($this->AppContainer, $this->ResponseFactory);
|
||||
$user = $auth->authenticate($request);
|
||||
if ($user !== null)
|
||||
{
|
||||
return $user;
|
||||
}
|
||||
|
||||
// Then by session cookie
|
||||
$auth = new SessionAuthMiddleware($this->AppContainer, $this->ResponseFactory);
|
||||
$user = $auth->authenticate($request);
|
||||
return $user;
|
||||
}
|
||||
// Then by session cookie
|
||||
$auth = new SessionAuthMiddleware($this->AppContainer, $this->ResponseFactory);
|
||||
$user = $auth->authenticate($request);
|
||||
return $user;
|
||||
}
|
||||
}
|
||||
|
@ -9,32 +9,32 @@ use Grocy\Services\UsersService;
|
||||
|
||||
class ReverseProxyAuthMiddleware extends AuthMiddleware
|
||||
{
|
||||
function authenticate(Request $request)
|
||||
{
|
||||
if (!defined('GROCY_SHOW_AUTH_VIEWS'))
|
||||
{
|
||||
define('GROCY_SHOW_AUTH_VIEWS', false);
|
||||
}
|
||||
function authenticate(Request $request)
|
||||
{
|
||||
if (!defined('GROCY_SHOW_AUTH_VIEWS'))
|
||||
{
|
||||
define('GROCY_SHOW_AUTH_VIEWS', false);
|
||||
}
|
||||
|
||||
$db = DatabaseService::getInstance()->GetDbConnection();
|
||||
$db = DatabaseService::getInstance()->GetDbConnection();
|
||||
|
||||
$username = $request->getHeader(GROCY_REVERSE_PROXY_AUTH_HEADER);
|
||||
|
||||
if (count($username) !== 1)
|
||||
{
|
||||
// Invalid configuration of Proxy
|
||||
throw new \Exception("ReverseProxyAuthMiddleware: Invalid username from proxy: " . var_dump($username));
|
||||
}
|
||||
$username = $request->getHeader(GROCY_REVERSE_PROXY_AUTH_HEADER);
|
||||
|
||||
$username = $username[0];
|
||||
if (count($username) !== 1)
|
||||
{
|
||||
// Invalid configuration of Proxy
|
||||
throw new \Exception("ReverseProxyAuthMiddleware: Invalid username from proxy: " . var_dump($username));
|
||||
}
|
||||
|
||||
$user = $db->users()->where('username', $username)->fetch();
|
||||
|
||||
if ($user == null)
|
||||
{
|
||||
$user = UsersService::getInstance()->CreateUser($username, '', '', '');
|
||||
}
|
||||
$username = $username[0];
|
||||
|
||||
return $user;
|
||||
}
|
||||
$user = $db->users()->where('username', $username)->fetch();
|
||||
|
||||
if ($user == null)
|
||||
{
|
||||
$user = UsersService::getInstance()->CreateUser($username, '', '', '');
|
||||
}
|
||||
|
||||
return $user;
|
||||
}
|
||||
}
|
||||
|
@ -10,29 +10,29 @@ use Grocy\Services\SessionService;
|
||||
|
||||
class SessionAuthMiddleware extends AuthMiddleware
|
||||
{
|
||||
public function __construct(\DI\Container $container, ResponseFactoryInterface $responseFactory)
|
||||
{
|
||||
parent::__construct($container, $responseFactory);
|
||||
$this->SessionCookieName = $this->AppContainer->get('LoginControllerInstance')->GetSessionCookieName();
|
||||
}
|
||||
public function __construct(\DI\Container $container, ResponseFactoryInterface $responseFactory)
|
||||
{
|
||||
parent::__construct($container, $responseFactory);
|
||||
$this->SessionCookieName = $this->AppContainer->get('LoginControllerInstance')->GetSessionCookieName();
|
||||
}
|
||||
|
||||
protected $SessionCookieName;
|
||||
protected $SessionCookieName;
|
||||
|
||||
function authenticate(Request $request)
|
||||
{
|
||||
if (!defined('GROCY_SHOW_AUTH_VIEWS'))
|
||||
{
|
||||
define('GROCY_SHOW_AUTH_VIEWS', true);
|
||||
}
|
||||
function authenticate(Request $request)
|
||||
{
|
||||
if (!defined('GROCY_SHOW_AUTH_VIEWS'))
|
||||
{
|
||||
define('GROCY_SHOW_AUTH_VIEWS', true);
|
||||
}
|
||||
|
||||
$sessionService = SessionService::getInstance();
|
||||
if (!isset($_COOKIE[$this->SessionCookieName]) || !$sessionService->IsValidSession($_COOKIE[$this->SessionCookieName]))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
return $sessionService->GetUserBySessionKey($_COOKIE[$this->SessionCookieName]);
|
||||
}
|
||||
}
|
||||
$sessionService = SessionService::getInstance();
|
||||
if (!isset($_COOKIE[$this->SessionCookieName]) || !$sessionService->IsValidSession($_COOKIE[$this->SessionCookieName]))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
return $sessionService->GetUserBySessionKey($_COOKIE[$this->SessionCookieName]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -79,7 +79,7 @@ a.discrete-link:focus {
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
|
||||
body.fullscreen-card {
|
||||
overflow: hidden;
|
||||
}
|
||||
@ -575,13 +575,13 @@ canvas.drawingBuffer {
|
||||
}
|
||||
|
||||
.print-view {
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
flex-basis: 100%;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
flex-basis: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.not-allowed {
|
||||
pointer-events: none;
|
||||
pointer-events: none;
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
@ -220,23 +220,23 @@
|
||||
}
|
||||
|
||||
.night-mode .note-editor.note-frame .note-editing-area .note-editable {
|
||||
color: #c1c1c1;
|
||||
background-color: #333131;
|
||||
color: #c1c1c1;
|
||||
background-color: #333131;
|
||||
}
|
||||
|
||||
.night-mode .bootstrap-datetimepicker-widget table td.day {
|
||||
background-color: #333131;
|
||||
background-color: #333131;
|
||||
}
|
||||
|
||||
.night-mode .bootstrap-datetimepicker-widget table td {
|
||||
background-color: #333131;
|
||||
background-color: #333131;
|
||||
}
|
||||
|
||||
.night-mode .bootstrap-datetimepicker-widget table td,
|
||||
.night-mode .bootstrap-datetimepicker-widget table td,
|
||||
.night-mode .bootstrap-datetimepicker-widget table th {
|
||||
background-color: #333131;
|
||||
background-color: #333131;
|
||||
}
|
||||
|
||||
.night-mode .dropdown-menu {
|
||||
background-color: #333131;
|
||||
background-color: #333131;
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ try
|
||||
}
|
||||
catch (ERequirementNotMet $ex)
|
||||
{
|
||||
die('Unable to run grocy: ' . $ex->getMessage());
|
||||
die('Unable to run grocy: ' . $ex->getMessage());
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/../app.php';
|
||||
|
@ -91,25 +91,25 @@ FindObjectInArrayByPropertyValue = function(array, propertyName, propertyValue)
|
||||
{
|
||||
if (array[i][propertyName] == propertyValue)
|
||||
{
|
||||
return array[i];
|
||||
}
|
||||
return array[i];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
FindAllObjectsInArrayByPropertyValue = function(array, propertyName, propertyValue)
|
||||
{
|
||||
var returnArray = [];
|
||||
|
||||
|
||||
for (var i = 0; i < array.length; i++)
|
||||
{
|
||||
if (array[i][propertyName] == propertyValue)
|
||||
{
|
||||
returnArray.push(array[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return returnArray;
|
||||
}
|
||||
|
||||
@ -137,7 +137,7 @@ function Delay(callable, delayMilliseconds)
|
||||
{
|
||||
var context = this;
|
||||
var args = arguments;
|
||||
|
||||
|
||||
clearTimeout(timer);
|
||||
timer = setTimeout(function()
|
||||
{
|
||||
@ -150,7 +150,7 @@ $.fn.isVisibleInViewport = function(extraHeightPadding = 0)
|
||||
{
|
||||
var elementTop = $(this).offset().top;
|
||||
var viewportTop = $(window).scrollTop() - extraHeightPadding;
|
||||
|
||||
|
||||
return elementTop + $(this).outerHeight() > viewportTop && elementTop < viewportTop + $(window).height();
|
||||
};
|
||||
|
||||
@ -163,7 +163,7 @@ function animateCSS(selector, animationName, callback, speed = "faster")
|
||||
{
|
||||
nodes.removeClass('animated').removeClass(speed).removeClass(animationName);
|
||||
nodes.unbind('animationend', handleAnimationEnd);
|
||||
|
||||
|
||||
if (typeof callback === 'function')
|
||||
{
|
||||
callback();
|
||||
|
@ -234,7 +234,7 @@ __t = function(text, ...placeholderValues)
|
||||
var text2 = text;
|
||||
Grocy.Api.Post('system/log-missing-localization', { "text": text2 });
|
||||
}
|
||||
|
||||
|
||||
return Grocy.Translator.__(text, ...placeholderValues)
|
||||
}
|
||||
__n = function(number, singularForm, pluralForm)
|
||||
@ -572,7 +572,7 @@ function RefreshLocaleNumberDisplay(rootSelector = "#page-content")
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$(this).text(parseFloat($(this).text()).toLocaleString(undefined, { minimumFractionDigits: 0, maximumFractionDigits: 2 }));
|
||||
});
|
||||
}
|
||||
@ -625,7 +625,7 @@ $(document).on("click", ".show-as-dialog-link", function(e)
|
||||
e.preventDefault();
|
||||
|
||||
var link = $(e.currentTarget).attr("href");
|
||||
|
||||
|
||||
bootbox.dialog({
|
||||
message: '<iframe height="650px" class="embed-responsive" src="' + link + '"></iframe>',
|
||||
size: 'large',
|
||||
|
@ -38,7 +38,7 @@ $(document).on("keyup", "#auto-night-mode-time-range-from, #auto-night-mode-time
|
||||
{
|
||||
var value = $(this).val();
|
||||
var valueIsValid = moment(value, "HH:mm", true).isValid();
|
||||
|
||||
|
||||
if (valueIsValid)
|
||||
{
|
||||
$(this).removeClass("bg-danger");
|
||||
@ -105,7 +105,7 @@ function CheckNightMode()
|
||||
$("body").removeClass("night-mode");
|
||||
$("#currently-inside-night-mode-range").prop("checked", false);
|
||||
$("#currently-inside-night-mode-range").trigger("change");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Grocy.UserId !== -1)
|
||||
|
@ -54,7 +54,7 @@ function OnBarcodeScanned(barcode)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
var bgClass = "";
|
||||
if (barcode != $("#expected_barcode").val())
|
||||
{
|
||||
@ -91,6 +91,6 @@ $(document).on("Grocy.BarcodeScanned", function(e, barcode, target)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
OnBarcodeScanned(barcode);
|
||||
});
|
||||
|
@ -7,7 +7,7 @@
|
||||
{
|
||||
jsonData.assignment_config = $("#assignment_config").val().join(",");
|
||||
}
|
||||
|
||||
|
||||
Grocy.FrontendHelpers.BeginUiBusy("chore-form");
|
||||
|
||||
if (Grocy.EditMode === 'create')
|
||||
|
@ -8,14 +8,14 @@ Grocy.Components.BarcodeScanner.CheckCapabilities = async function()
|
||||
if (typeof track.getCapabilities === 'function') {
|
||||
capabilities = track.getCapabilities();
|
||||
}
|
||||
|
||||
|
||||
// If there is more than 1 camera, show the camera selection
|
||||
var cameras = await Quagga.CameraAccess.enumerateVideoDevices();
|
||||
var cameraSelect = document.querySelector('.cameraSelect-wrapper');
|
||||
if (cameraSelect) {
|
||||
cameraSelect.style.display = cameras.length > 1 ? 'inline-block' : 'none';
|
||||
}
|
||||
|
||||
|
||||
// Check if the camera is capable to turn on a torch.
|
||||
var canTorch = typeof capabilities.torch === 'boolean' && capabilities.torch
|
||||
// Remove the torch button, if either the device can not torch or AutoTorchOn is set.
|
||||
@ -133,7 +133,7 @@ Grocy.Components.BarcodeScanner.StartScanning = function()
|
||||
Grocy.Components.BarcodeScanner.StopScanning = function()
|
||||
{
|
||||
Quagga.stop();
|
||||
|
||||
|
||||
Grocy.Components.BarcodeScanner.DecodedCodesCount = 0;
|
||||
Grocy.Components.BarcodeScanner.DecodedCodesErrorCount = 0;
|
||||
|
||||
@ -143,9 +143,9 @@ Grocy.Components.BarcodeScanner.StopScanning = function()
|
||||
Grocy.Components.BarcodeScanner.TorchOn = function(track)
|
||||
{
|
||||
if (track) {
|
||||
track.applyConstraints({
|
||||
track.applyConstraints({
|
||||
advanced: [
|
||||
{
|
||||
{
|
||||
torch: true
|
||||
}
|
||||
]
|
||||
@ -214,7 +214,7 @@ $(document).on("click", "#barcodescanner-start-button", async function(e)
|
||||
}
|
||||
|
||||
Grocy.Components.BarcodeScanner.CurrentTarget = inputElement.attr("data-target");
|
||||
|
||||
|
||||
var dialog = bootbox.dialog({
|
||||
message: '<div id="barcodescanner-container" class="col"><div id="barcodescanner-livestream"></div></div>',
|
||||
title: __t('Scan a barcode'),
|
||||
@ -233,8 +233,8 @@ $(document).on("click", "#barcodescanner-start-button", async function(e)
|
||||
{
|
||||
Grocy.Components.BarcodeScanner.TorchOn(Quagga.CameraAccess.getActiveTrack());
|
||||
return false;
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
cancel: {
|
||||
label: __t('Cancel'),
|
||||
className: 'btn-secondary responsive-button',
|
||||
@ -245,11 +245,11 @@ $(document).on("click", "#barcodescanner-start-button", async function(e)
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Add camera select to existing dialog
|
||||
dialog.find('.bootbox-body').append('<div class="form-group py-0 my-1 cameraSelect-wrapper"><select class="form-control cameraSelect"><select class="form-control cameraSelect" style="display: none"></select></div>');
|
||||
var cameraSelect = document.querySelector('.cameraSelect');
|
||||
|
||||
|
||||
var cameras = await Quagga.CameraAccess.enumerateVideoDevices();
|
||||
cameras.forEach(camera => {
|
||||
var option = document.createElement("option");
|
||||
@ -266,7 +266,7 @@ $(document).on("click", "#barcodescanner-start-button", async function(e)
|
||||
Quagga.stop();
|
||||
Grocy.Components.BarcodeScanner.StartScanning();
|
||||
};
|
||||
|
||||
|
||||
Grocy.Components.BarcodeScanner.StartScanning();
|
||||
});
|
||||
|
||||
|
@ -132,7 +132,7 @@ Grocy.Components.DateTimePicker.GetInputElement().on('keyup', function(e)
|
||||
var centuryEnd = Number.parseInt(now.getFullYear().toString().substring(0, 2) + '99');
|
||||
var format = Grocy.Components.DateTimePicker.GetInputElement().data('format');
|
||||
var nextInputElement = $(Grocy.Components.DateTimePicker.GetInputElement().data('next-input-selector'));
|
||||
|
||||
|
||||
//If input is empty and any arrow key is pressed, set date to today
|
||||
if (value.length === 0 && (e.keyCode === 38 || e.keyCode === 40 || e.keyCode === 37 || e.keyCode === 39))
|
||||
{
|
||||
@ -224,7 +224,7 @@ Grocy.Components.DateTimePicker.GetInputElement().on('keyup', function(e)
|
||||
if ($(element).hasAttr("required"))
|
||||
{
|
||||
element.setCustomValidity("error");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -132,7 +132,7 @@ Grocy.Components.DateTimePicker2.GetInputElement().on('keyup', function(e)
|
||||
var centuryEnd = Number.parseInt(now.getFullYear().toString().substring(0, 2) + '99');
|
||||
var format = Grocy.Components.DateTimePicker2.GetInputElement().data('format');
|
||||
var nextInputElement = $(Grocy.Components.DateTimePicker2.GetInputElement().data('next-input-selector'));
|
||||
|
||||
|
||||
//If input is empty and any arrow key is pressed, set date to today
|
||||
if (value.length === 0 && (e.keyCode === 38 || e.keyCode === 40 || e.keyCode === 37 || e.keyCode === 39))
|
||||
{
|
||||
@ -224,7 +224,7 @@ Grocy.Components.DateTimePicker2.GetInputElement().on('keyup', function(e)
|
||||
if ($(element).hasAttr("required"))
|
||||
{
|
||||
element.setCustomValidity("error");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -50,7 +50,7 @@ Grocy.Components.ProductAmountPicker.SetQuantityUnit = function(quId)
|
||||
Grocy.Components.ProductAmountPicker.AllowAnyQu = function(keepInitialQu = false)
|
||||
{
|
||||
Grocy.Components.ProductAmountPicker.AllowAnyQuEnabled = true;
|
||||
|
||||
|
||||
$("#qu_id").find("option").remove().end();
|
||||
Grocy.QuantityUnits.forEach(qu =>
|
||||
{
|
||||
|
@ -156,7 +156,7 @@ Grocy.Components.ProductCard.Refresh = function(productId)
|
||||
{
|
||||
key = dataPoint.shopping_location.name
|
||||
}
|
||||
|
||||
|
||||
if (!datasets[key]) {
|
||||
datasets[key] = []
|
||||
}
|
||||
|
@ -130,13 +130,13 @@ $('#product_id_text_input').on('blur', function(e)
|
||||
{
|
||||
if (Grocy.Components.ProductPicker.GetPicker().hasClass("combobox-menu-visible"))
|
||||
{
|
||||
return;
|
||||
return;
|
||||
}
|
||||
$('#product_id').attr("barcode", "null");
|
||||
|
||||
var input = $('#product_id_text_input').val().toString();
|
||||
var possibleOptionElement = $("#product_id option[data-additional-searchdata*=\"" + input + ",\"]").first();
|
||||
|
||||
|
||||
if (GetUriParam('addbarcodetoselection') === undefined && input.length > 0 && possibleOptionElement.length > 0)
|
||||
{
|
||||
$('#product_id').val(possibleOptionElement.val());
|
||||
@ -235,7 +235,7 @@ $(document).on("Grocy.BarcodeScanned", function(e, barcode, target)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Don't know why the blur event does not fire immediately ... this works...
|
||||
|
||||
Grocy.Components.ProductPicker.GetInputElement().focusout();
|
||||
@ -243,7 +243,7 @@ $(document).on("Grocy.BarcodeScanned", function(e, barcode, target)
|
||||
Grocy.Components.ProductPicker.GetInputElement().blur();
|
||||
|
||||
Grocy.Components.ProductPicker.GetInputElement().val(barcode);
|
||||
|
||||
|
||||
setTimeout(function()
|
||||
{
|
||||
Grocy.Components.ProductPicker.GetInputElement().focusout();
|
||||
|
@ -69,7 +69,7 @@ Grocy.Components.UserfieldsForm.Load = function()
|
||||
$.each(result, function(key, value)
|
||||
{
|
||||
var input = $(".userfield-input[data-userfield-name='" + key + "']");
|
||||
|
||||
|
||||
if (input.attr("type") == "checkbox" && value == 1)
|
||||
{
|
||||
input.prop("checked", true);
|
||||
|
@ -215,7 +215,7 @@ $("#location_id").on('change', function(e)
|
||||
amount: stockEntry.amount,
|
||||
text: __t("Amount: %1$s; Expires on %2$s; Bought on %3$s", stockEntry.amount, moment(stockEntry.best_before_date).format("YYYY-MM-DD"), moment(stockEntry.purchased_date).format("YYYY-MM-DD")) + "; " + openTxt
|
||||
}));
|
||||
|
||||
|
||||
sumValue = sumValue + parseFloat(stockEntry.amount);
|
||||
|
||||
if (stockEntry.stock_id == stockId)
|
||||
|
@ -24,7 +24,7 @@
|
||||
{
|
||||
jsonData.location_id = Grocy.Components.LocationPicker.GetValue();
|
||||
}
|
||||
|
||||
|
||||
jsonData.price = price;
|
||||
|
||||
var bookingResponse = null;
|
||||
@ -33,7 +33,7 @@
|
||||
function(result)
|
||||
{
|
||||
bookingResponse = result;
|
||||
|
||||
|
||||
var addBarcode = GetUriParam('addbarcodetoselection');
|
||||
if (addBarcode !== undefined)
|
||||
{
|
||||
@ -62,7 +62,7 @@
|
||||
function(result)
|
||||
{
|
||||
var successMessage = __t('Stock amount of %1$s is now %2$s', result.product.name, result.stock_amount + " " + __n(result.stock_amount, result.quantity_unit_stock.name, result.quantity_unit_stock.name_plural)) + '<br><a class="btn btn-secondary btn-sm mt-2" href="#" onclick="UndoStockTransaction(\'' + bookingResponse.transaction_id + '\')"><i class="fas fa-undo"></i> ' + __t("Undo") + '</a>';
|
||||
|
||||
|
||||
if (GetUriParam("embedded") !== undefined)
|
||||
{
|
||||
window.parent.postMessage(WindowMessageBag("ProductChanged", jsonForm.product_id), Grocy.BaseUrl);
|
||||
@ -245,7 +245,7 @@ $('#new_amount').on('keyup', function(e)
|
||||
function(productDetails)
|
||||
{
|
||||
var productStockAmount = parseFloat(productDetails.stock_amount || parseFloat('0'));
|
||||
|
||||
|
||||
var containerWeight = parseFloat("0");
|
||||
if (productDetails.product.enable_tare_weight_handling == 1)
|
||||
{
|
||||
|
@ -48,7 +48,7 @@ var calendar = $("#calendar").fullCalendar({
|
||||
|
||||
var weekRecipeName = view.start.year().toString() + "-" + ((view.start.week() - 1).toString().padStart(2, "0")).toString();
|
||||
var weekRecipe = FindObjectInArrayByPropertyValue(internalRecipes, "name", weekRecipeName);
|
||||
|
||||
|
||||
var weekCosts = 0;
|
||||
var weekRecipeOrderMissingButtonHtml = "";
|
||||
var weekRecipeConsumeButtonHtml = "";
|
||||
@ -66,7 +66,7 @@ var calendar = $("#calendar").fullCalendar({
|
||||
{
|
||||
weekRecipeOrderMissingButtonDisabledClasses = "disabled";
|
||||
}
|
||||
|
||||
|
||||
var weekRecipeConsumeButtonDisabledClasses = "";
|
||||
if (FindObjectInArrayByPropertyValue(recipesResolved, "recipe_id", weekRecipe.id).need_fulfilled == 0 || weekCosts == 0)
|
||||
{
|
||||
@ -174,7 +174,7 @@ var calendar = $("#calendar").fullCalendar({
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (productDetails.last_price === null)
|
||||
{
|
||||
productDetails.last_price = 0;
|
||||
@ -458,7 +458,7 @@ $('#save-add-note-button').on('click', function(e)
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
|
||||
$('#save-add-product-button').on('click', function(e)
|
||||
@ -562,7 +562,7 @@ $(document).on('click', '.recipe-order-missing-button', function(e)
|
||||
// Remove the focus from the current button
|
||||
// to prevent that the tooltip stays until clicked anywhere else
|
||||
document.activeElement.blur();
|
||||
|
||||
|
||||
var objectName = $(e.currentTarget).attr('data-recipe-name');
|
||||
var objectId = $(e.currentTarget).attr('data-recipe-id');
|
||||
var button = $(this);
|
||||
|
@ -482,7 +482,7 @@ $(document).on('click', '.barcode-delete-button', function(e)
|
||||
});
|
||||
});
|
||||
|
||||
$('#qu_id_purchase').blur(function(e)
|
||||
$('#qu_id_purchase').blur(function(e)
|
||||
{
|
||||
// Preset the stock quantity unit with the purchase quantity unit, if the stock quantity unit is unset.
|
||||
var QuIdStock = $('#qu_id_stock');
|
||||
|
@ -153,7 +153,7 @@ if (Grocy.Components.ProductPicker !== undefined)
|
||||
$('#product_id').attr("barcode-qu-factor-purchase-to-stock", "null");
|
||||
$('#product_id').attr("barcode-shopping-location-id", "null");
|
||||
}
|
||||
},
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
console.error(xhr);
|
||||
@ -171,7 +171,7 @@ if (Grocy.Components.ProductPicker !== undefined)
|
||||
{
|
||||
|
||||
$('#price').val(parseFloat(productDetails.last_price).toLocaleString({ minimumFractionDigits: 2, maximumFractionDigits: 2 }));
|
||||
|
||||
|
||||
var qu_factor_purchase_to_stock = null;
|
||||
var barcode_shopping_location_id = null;
|
||||
|
||||
@ -184,14 +184,14 @@ if (Grocy.Components.ProductPicker !== undefined)
|
||||
{
|
||||
if (productDetails.last_qu_factor_purchase_to_stock != null)
|
||||
{
|
||||
qu_factor_purchase_to_stock = productDetails.last_qu_factor_purchase_to_stock;
|
||||
qu_factor_purchase_to_stock = productDetails.last_qu_factor_purchase_to_stock;
|
||||
}
|
||||
else
|
||||
{
|
||||
qu_factor_purchase_to_stock = productDetails.product.qu_factor_purchase_to_stock;
|
||||
qu_factor_purchase_to_stock = productDetails.product.qu_factor_purchase_to_stock;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (Grocy.FeatureFlags.GROCY_FEATURE_FLAG_STOCK_PRICE_TRACKING) {
|
||||
if (barcode_shopping_location_id != null)
|
||||
{
|
||||
|
@ -36,10 +36,10 @@
|
||||
Grocy.FrontendHelpers.ShowGenericError('Error while saving, probably this item already exists', xhr.response)
|
||||
}
|
||||
);
|
||||
if ($("#create_inverse").is(":checked"))
|
||||
if ($("#create_inverse").is(":checked"))
|
||||
{
|
||||
jsonData.to_qu_id = inverse_to_qu_id;
|
||||
jsonData.from_qu_id = inverse_from_qu_id;
|
||||
jsonData.to_qu_id = inverse_to_qu_id;
|
||||
jsonData.from_qu_id = inverse_from_qu_id;
|
||||
jsonData.factor = 1 / jsonData.factor;
|
||||
|
||||
//Create Inverse
|
||||
@ -124,7 +124,7 @@ $("#create_inverse").on("change", function()
|
||||
|
||||
if (value)
|
||||
{
|
||||
$('#qu-conversion-inverse-info').removeClass('d-none');
|
||||
$('#qu-conversion-inverse-info').removeClass('d-none');
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1,5 +1,5 @@
|
||||
function saveRecipePicture(result, location)
|
||||
{
|
||||
{
|
||||
$recipeId = Grocy.EditObjectId || result.created_object_id;
|
||||
Grocy.Components.UserfieldsForm.Save(() =>
|
||||
{
|
||||
@ -38,7 +38,7 @@ $('.save-recipe').on('click', function(e)
|
||||
}
|
||||
|
||||
const location = $(e.currentTarget).attr('data-location') == 'return' ? '/recipes?recipe=' : '/recipe/';
|
||||
|
||||
|
||||
if(Grocy.EditMode == 'create') {
|
||||
console.log(jsonData);
|
||||
Grocy.Api.Post('objects/recipes', jsonData,
|
||||
@ -210,7 +210,7 @@ $(document).on('click', '.recipe-pos-edit-button', function(e)
|
||||
|
||||
var productId = $(e.currentTarget).attr("data-product-id");
|
||||
var recipePosId = $(e.currentTarget).attr('data-recipe-pos-id');
|
||||
|
||||
|
||||
bootbox.dialog({
|
||||
message: '<iframe height="650px" class="embed-responsive" src="' + U("/recipe/") + Grocy.EditObjectId.toString() + '/pos/' + recipePosId.toString() + '?embedded&product=' + productId.toString() + '"></iframe>',
|
||||
size: 'large',
|
||||
@ -234,7 +234,7 @@ $(document).on('click', '.recipe-include-edit-button', function (e)
|
||||
var id = $(e.currentTarget).attr('data-recipe-include-id');
|
||||
var recipeId = $(e.currentTarget).attr('data-recipe-included-recipe-id');
|
||||
var recipeServings = $(e.currentTarget).attr('data-recipe-included-recipe-servings');
|
||||
|
||||
|
||||
Grocy.Api.Put('objects/recipes/' + Grocy.EditObjectId, $('#recipe-form').serializeJSON(),
|
||||
function(result)
|
||||
{
|
||||
|
@ -49,12 +49,12 @@ Grocy.Components.ProductPicker.GetPicker().on('change', function(e)
|
||||
if (productId)
|
||||
{
|
||||
Grocy.Components.ProductCard.Refresh(productId);
|
||||
|
||||
|
||||
Grocy.Api.Get('stock/products/' + productId,
|
||||
function(productDetails)
|
||||
{
|
||||
Grocy.RecipePosFormProductChangeCount++;
|
||||
|
||||
|
||||
if (Grocy.RecipePosFormProductChangeCount < 3) // This triggers twice on initial page load, however
|
||||
{
|
||||
Grocy.Components.ProductAmountPicker.Reload(productDetails.product.id, productDetails.quantity_unit_stock.id, true);
|
||||
|
@ -62,7 +62,7 @@ $("#search").on("keyup", Delay(function()
|
||||
|
||||
$(".recipe-gallery-item").removeClass("d-none");
|
||||
console.log( $(".recipe-gallery-item .card-title:not(:contains_case_insensitive(" + value + "))"));
|
||||
|
||||
|
||||
$(".recipe-gallery-item .card-title:not(:contains_case_insensitive(" + value + "))").parent().parent().parent().addClass("d-none");
|
||||
}, 200));
|
||||
|
||||
@ -80,7 +80,7 @@ $("#status-filter").on("change", function()
|
||||
$(".recipe-delete").on('click', function(e)
|
||||
{
|
||||
e.preventDefault();
|
||||
|
||||
|
||||
var objectName = $(e.currentTarget).attr('data-recipe-name');
|
||||
var objectId = $(e.currentTarget).attr('data-recipe-id');
|
||||
|
||||
@ -245,7 +245,7 @@ $(".recipe-fullscreen").on('click', function(e)
|
||||
|
||||
$(".recipe-print").on('click', function(e)
|
||||
{
|
||||
e.preventDefault();
|
||||
e.preventDefault();
|
||||
|
||||
$("#selectedRecipeCard").removeClass("fullscreen");
|
||||
$("body").removeClass("fullscreen-card");
|
||||
|
@ -287,7 +287,7 @@ $(document).on('click', '.order-listitem-button', function(e)
|
||||
Grocy.FrontendHelpers.BeginUiBusy();
|
||||
|
||||
var listItemId = $(e.currentTarget).attr('data-item-id');
|
||||
|
||||
|
||||
var done = 1;
|
||||
if ($(e.currentTarget).attr('data-item-done') == 1)
|
||||
{
|
||||
@ -319,7 +319,7 @@ $(document).on('click', '.order-listitem-button', function(e)
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
|
||||
var statusInfoCell = $("#shoppinglistitem-" + listItemId + "-status-info");
|
||||
if (done == 1)
|
||||
{
|
||||
@ -403,7 +403,7 @@ $(".switch-view-mode-button").on('click', function(e)
|
||||
|
||||
if ($("body").hasClass("fullscreen-card"))
|
||||
{
|
||||
window.location.hash = "#compact";
|
||||
window.location.hash = "#compact";
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -116,7 +116,7 @@ Grocy.Components.ProductPicker.GetPicker().on('change', function(e)
|
||||
function (productDetails)
|
||||
{
|
||||
$('#amount_qu_unit').text(productDetails.quantity_unit_purchase.name);
|
||||
|
||||
|
||||
$('#amount').focus();
|
||||
Grocy.FrontendHelpers.ValidateForm('shoppinglist-form');
|
||||
},
|
||||
|
@ -15,7 +15,7 @@ $.fn.dataTable.ext.search.push(function(settings, data, dataIndex)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
@ -90,7 +90,7 @@ $(document).on('click', '.product-open-button', function(e)
|
||||
var specificStockEntryId = $(e.currentTarget).attr('data-stock-id');
|
||||
var stockRowId = $(e.currentTarget).attr('data-stockrow-id');
|
||||
var button = $(e.currentTarget);
|
||||
|
||||
|
||||
Grocy.Api.Post('stock/products/' + productId + '/open', { 'amount': 1, 'stock_entry_id': specificStockEntryId },
|
||||
function(bookingResponse)
|
||||
{
|
||||
@ -125,7 +125,7 @@ function RefreshStockEntryRow(stockRowId)
|
||||
{
|
||||
window.location.reload();
|
||||
}
|
||||
|
||||
|
||||
if (result == null || result.amount == 0)
|
||||
{
|
||||
animateCSS("#stock-" + stockRowId + "-row", "fadeOut", function()
|
||||
@ -175,7 +175,7 @@ function RefreshStockEntryRow(stockRowId)
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
$('#stock-' + stockRowId + '-price').text(result.price);
|
||||
$('#stock-' + stockRowId + '-qu-factor-purchase-to-stock').text(result.qu_factor_purchase_to_stock);
|
||||
$('#stock-' + stockRowId + '-purchased-date').text(result.purchased_date);
|
||||
|
@ -39,7 +39,7 @@ $("#product-group-filter").on("change", function()
|
||||
{
|
||||
value = "xx" + value + "xx";
|
||||
}
|
||||
|
||||
|
||||
stockOverviewTable.column(7).search(value).draw();
|
||||
});
|
||||
|
||||
@ -116,7 +116,7 @@ $(document).on('click', '.product-consume-button', function(e)
|
||||
{
|
||||
var toastMessage = __t('Removed %1$s of %2$s from stock', consumeAmount.toString() + " " + __n(consumeAmount, result.quantity_unit_stock.name, result.quantity_unit_stock.name_plural), result.product.name) + '<br><a class="btn btn-secondary btn-sm mt-2" href="#" onclick="UndoStockTransaction(\'' + bookingResponse.transaction_id + '\')"><i class="fas fa-undo"></i> ' + __t("Undo") + '</a>';
|
||||
}
|
||||
|
||||
|
||||
if (wasSpoiled)
|
||||
{
|
||||
toastMessage += " (" + __t("Spoiled") + ")";
|
||||
@ -244,7 +244,7 @@ function RefreshProductRow(productId)
|
||||
var expiringThreshold = moment().add($("#info-expiring-products").data("next-x-days"), "days");
|
||||
var now = moment();
|
||||
var nextBestBeforeDate = moment(result.next_best_before_date);
|
||||
|
||||
|
||||
productRow.removeClass("table-warning");
|
||||
productRow.removeClass("table-danger");
|
||||
productRow.removeClass("table-info");
|
||||
|
@ -55,7 +55,7 @@ $('#user-form input').keydown(function (event)
|
||||
if (event.keyCode === 13) //Enter
|
||||
{
|
||||
event.preventDefault();
|
||||
|
||||
|
||||
if (document.getElementById('user-form').checkValidity() === false) //There is at least one validation error
|
||||
{
|
||||
return false;
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
var jsonData = {};
|
||||
jsonData.userentity_id = Grocy.EditObjectParentId;
|
||||
|
||||
|
||||
Grocy.FrontendHelpers.BeginUiBusy("userobject-form");
|
||||
|
||||
if (Grocy.EditMode === 'create')
|
||||
|
@ -1,42 +1,42 @@
|
||||
$('input.permission-cb').click(
|
||||
function () {
|
||||
check_hierachy(this.checked, this.name);
|
||||
}
|
||||
function () {
|
||||
check_hierachy(this.checked, this.name);
|
||||
}
|
||||
);
|
||||
|
||||
function check_hierachy(checked, name) {
|
||||
var disabled = checked;
|
||||
$('#permission-sub-' + name).find('input.permission-cb')
|
||||
.prop('checked', disabled)
|
||||
.attr('disabled', disabled);
|
||||
var disabled = checked;
|
||||
$('#permission-sub-' + name).find('input.permission-cb')
|
||||
.prop('checked', disabled)
|
||||
.attr('disabled', disabled);
|
||||
}
|
||||
|
||||
$('#permission-save').click(
|
||||
function () {
|
||||
var permission_list = $('input.permission-cb')
|
||||
.filter(function () {
|
||||
return $(this).prop('checked') && !$(this).attr('disabled');
|
||||
}).map(function () {
|
||||
return $(this).data('perm-id');
|
||||
}).toArray();
|
||||
Grocy.Api.Put('users/' + Grocy.EditObjectId + '/permissions', {
|
||||
'permissions': permission_list,
|
||||
}, function (result) {
|
||||
toastr.success(__t("Permissions saved"));
|
||||
}, function (xhr) {
|
||||
toastr.error(__t(JSON.parse(xhr.response).error_message));
|
||||
}
|
||||
);
|
||||
}
|
||||
function () {
|
||||
var permission_list = $('input.permission-cb')
|
||||
.filter(function () {
|
||||
return $(this).prop('checked') && !$(this).attr('disabled');
|
||||
}).map(function () {
|
||||
return $(this).data('perm-id');
|
||||
}).toArray();
|
||||
Grocy.Api.Put('users/' + Grocy.EditObjectId + '/permissions', {
|
||||
'permissions': permission_list,
|
||||
}, function (result) {
|
||||
toastr.success(__t("Permissions saved"));
|
||||
}, function (xhr) {
|
||||
toastr.error(__t(JSON.parse(xhr.response).error_message));
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
if (Grocy.EditObjectId == Grocy.UserId) {
|
||||
$('input.permission-cb[name=ADMIN]').click(function () {
|
||||
if (!this.checked) {
|
||||
if (!confirm(__t('Are you sure you want to stop being an ADMIN?'))) {
|
||||
this.checked = true;
|
||||
check_hierachy(this.checked, this.name);
|
||||
}
|
||||
}
|
||||
})
|
||||
$('input.permission-cb[name=ADMIN]').click(function () {
|
||||
if (!this.checked) {
|
||||
if (!confirm(__t('Are you sure you want to stop being an ADMIN?'))) {
|
||||
this.checked = true;
|
||||
check_hierachy(this.checked, this.name);
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
16
routes.php
16
routes.php
@ -33,9 +33,9 @@ $app->group('', function(RouteCollectorProxy $group)
|
||||
// User routes
|
||||
$group->get('/users', '\Grocy\Controllers\UsersController:UsersList');
|
||||
$group->get('/user/{userId}', '\Grocy\Controllers\UsersController:UserEditForm');
|
||||
$group->get('/user/{userId}/permissions', '\Grocy\Controllers\UsersController:PermissionList');
|
||||
$group->get('/user/{userId}/permissions', '\Grocy\Controllers\UsersController:PermissionList');
|
||||
|
||||
// Stock routes
|
||||
// Stock routes
|
||||
if (GROCY_FEATURE_FLAG_STOCK)
|
||||
{
|
||||
$group->get('/stockoverview', '\Grocy\Controllers\StockController:Overview');
|
||||
@ -145,10 +145,10 @@ $app->group('/api', function(RouteCollectorProxy $group)
|
||||
|
||||
// System
|
||||
$group->get('/system/info', '\Grocy\Controllers\SystemApiController:GetSystemInfo');
|
||||
$group->get('/system/db-changed-time', '\Grocy\Controllers\SystemApiController:GetDbChangedTime');
|
||||
$group->get('/system/db-changed-time', '\Grocy\Controllers\SystemApiController:GetDbChangedTime');
|
||||
$group->get('/system/config', '\Grocy\Controllers\SystemApiController:GetConfig');
|
||||
$group->post('/system/log-missing-localization', '\Grocy\Controllers\SystemApiController:LogMissingLocalization');
|
||||
|
||||
|
||||
// Generic entity interaction
|
||||
$group->get('/objects/{entity}', '\Grocy\Controllers\GenericEntityApiController:GetObjects');
|
||||
$group->get('/objects/{entity}/{objectId}', '\Grocy\Controllers\GenericEntityApiController:GetObject');
|
||||
@ -169,11 +169,11 @@ $app->group('/api', function(RouteCollectorProxy $group)
|
||||
$group->post('/users', '\Grocy\Controllers\UsersApiController:CreateUser');
|
||||
$group->put('/users/{userId}', '\Grocy\Controllers\UsersApiController:EditUser');
|
||||
$group->delete('/users/{userId}', '\Grocy\Controllers\UsersApiController:DeleteUser');
|
||||
$group->get('/users/{userId}/permissions', '\Grocy\Controllers\UsersApiController:ListPermissions');
|
||||
$group->post('/users/{userId}/permissions', '\Grocy\Controllers\UsersApiController:AddPermission');
|
||||
$group->put('/users/{userId}/permissions', '\Grocy\Controllers\UsersApiController:SetPermissions');
|
||||
$group->get('/users/{userId}/permissions', '\Grocy\Controllers\UsersApiController:ListPermissions');
|
||||
$group->post('/users/{userId}/permissions', '\Grocy\Controllers\UsersApiController:AddPermission');
|
||||
$group->put('/users/{userId}/permissions', '\Grocy\Controllers\UsersApiController:SetPermissions');
|
||||
|
||||
// User
|
||||
// User
|
||||
$group->get('/user/settings', '\Grocy\Controllers\UsersApiController:GetUserSettings');
|
||||
$group->get('/user/settings/{settingKey}', '\Grocy\Controllers\UsersApiController:GetUserSetting');
|
||||
$group->put('/user/settings/{settingKey}', '\Grocy\Controllers\UsersApiController:SetUserSetting');
|
||||
|
@ -15,7 +15,7 @@ class BaseService
|
||||
public static function getInstance()
|
||||
{
|
||||
$className = get_called_class();
|
||||
if(!isset(self::$instances[$className]))
|
||||
if(!isset(self::$instances[$className]))
|
||||
{
|
||||
self::$instances[$className] = new $className();
|
||||
}
|
||||
@ -23,7 +23,7 @@ class BaseService
|
||||
return self::$instances[$className];
|
||||
}
|
||||
|
||||
protected function getDatabaseService()
|
||||
protected function getDatabaseService()
|
||||
{
|
||||
return DatabaseService::getInstance();
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ class ChoresService extends BaseService
|
||||
{
|
||||
throw new \Exception('Chore does not exist');
|
||||
}
|
||||
|
||||
|
||||
$users = $this->getUsersService()->GetUsersAsDto();
|
||||
|
||||
$chore = $this->getDatabase()->chores($choreId);
|
||||
|
@ -28,7 +28,7 @@ class DatabaseService
|
||||
return GROCY_DATAPATH . '/grocy.db';
|
||||
}
|
||||
|
||||
private static $DbConnectionRaw = null;
|
||||
private static $DbConnectionRaw = null;
|
||||
/**
|
||||
* @return \PDO
|
||||
*/
|
||||
|
@ -12,7 +12,7 @@ class DemoDataGeneratorService extends BaseService
|
||||
$this->LocalizationService = new LocalizationService(GROCY_CULTURE);
|
||||
}
|
||||
|
||||
protected $LocalizationService;
|
||||
protected $LocalizationService;
|
||||
|
||||
public function PopulateDemoData()
|
||||
{
|
||||
|
@ -21,16 +21,16 @@ class LocalizationService
|
||||
|
||||
|
||||
protected function getDatabaseService()
|
||||
{
|
||||
return DatabaseService::getInstance();
|
||||
}
|
||||
{
|
||||
return DatabaseService::getInstance();
|
||||
}
|
||||
|
||||
protected function getdatabase()
|
||||
{
|
||||
return $this->getDatabaseService()->GetDbConnection();
|
||||
}
|
||||
protected function getdatabase()
|
||||
{
|
||||
return $this->getDatabaseService()->GetDbConnection();
|
||||
}
|
||||
|
||||
public static function getInstance(string $culture)
|
||||
public static function getInstance(string $culture)
|
||||
{
|
||||
if (!in_array($culture, self::$instanceMap))
|
||||
{
|
||||
@ -92,10 +92,10 @@ class LocalizationService
|
||||
{
|
||||
$this->Po = $this->Po->mergeWith(Translations::fromPoFile(__DIR__ . "/../localization/$culture/userfield_types.po"));
|
||||
}
|
||||
if (file_exists(__DIR__ . "/../localization/$culture/permissions.po"))
|
||||
{
|
||||
$this->Po = $this->Po->mergeWith(Translations::fromPoFile(__DIR__ . "/../localization/$culture/permissions.po"));
|
||||
}
|
||||
if (file_exists(__DIR__ . "/../localization/$culture/permissions.po"))
|
||||
{
|
||||
$this->Po = $this->Po->mergeWith(Translations::fromPoFile(__DIR__ . "/../localization/$culture/permissions.po"));
|
||||
}
|
||||
if (GROCY_MODE !== 'production' && file_exists(__DIR__ . "/../localization/$culture/demo_data.po"))
|
||||
{
|
||||
$this->Po = $this->Po->mergeWith(Translations::fromPoFile(__DIR__ . "/../localization/$culture/demo_data.po"));
|
||||
|
@ -14,16 +14,16 @@ class StockService extends BaseService
|
||||
const TRANSACTION_TYPE_PRODUCT_OPENED = 'product-opened';
|
||||
const TRANSACTION_TYPE_SELF_PRODUCTION = 'self-production';
|
||||
|
||||
public function GetCurrentStockOverview()
|
||||
{
|
||||
if (!GROCY_FEATURE_SETTING_STOCK_COUNT_OPENED_PRODUCTS_AGAINST_MINIMUM_STOCK_AMOUNT) {
|
||||
return $this->getDatabase()->uihelper_stock_current_overview();
|
||||
} else {
|
||||
return $this->getDatabase()->uihelper_stock_current_overview_including_opened();
|
||||
}
|
||||
}
|
||||
public function GetCurrentStockOverview()
|
||||
{
|
||||
if (!GROCY_FEATURE_SETTING_STOCK_COUNT_OPENED_PRODUCTS_AGAINST_MINIMUM_STOCK_AMOUNT) {
|
||||
return $this->getDatabase()->uihelper_stock_current_overview();
|
||||
} else {
|
||||
return $this->getDatabase()->uihelper_stock_current_overview_including_opened();
|
||||
}
|
||||
}
|
||||
|
||||
public function GetCurrentStock($includeNotInStockButMissingProducts = false)
|
||||
public function GetCurrentStock($includeNotInStockButMissingProducts = false)
|
||||
{
|
||||
$sql = 'SELECT * FROM stock_current';
|
||||
if ($includeNotInStockButMissingProducts)
|
||||
@ -37,7 +37,7 @@ class StockService extends BaseService
|
||||
$sql = 'SELECT * FROM stock_current WHERE best_before_date IS NOT NULL UNION SELECT id, 0, 0, 0, 0, null, 0, 0, 0 FROM ' . $missingProductsView . ' WHERE id NOT IN (SELECT product_id FROM stock_current)';
|
||||
}
|
||||
$currentStockMapped = $this->getDatabaseService()->ExecuteDbQuery($sql)->fetchAll(\PDO::FETCH_GROUP|\PDO::FETCH_OBJ);
|
||||
|
||||
|
||||
$relevantProducts = $this->getDatabase()->products()->where('id IN (SELECT product_id FROM (' . $sql . ') x)');
|
||||
foreach ($relevantProducts as $product)
|
||||
{
|
||||
|
@ -23,13 +23,13 @@ class UserfieldsService extends BaseService
|
||||
protected $OpenApiSpec = null;
|
||||
|
||||
protected function getOpenApispec()
|
||||
{
|
||||
if($this->OpenApiSpec == null)
|
||||
{
|
||||
$this->OpenApiSpec = json_decode(file_get_contents(__DIR__ . '/../grocy.openapi.json'));
|
||||
}
|
||||
return $this->OpenApiSpec;
|
||||
}
|
||||
{
|
||||
if($this->OpenApiSpec == null)
|
||||
{
|
||||
$this->OpenApiSpec = json_decode(file_get_contents(__DIR__ . '/../grocy.openapi.json'));
|
||||
}
|
||||
return $this->OpenApiSpec;
|
||||
}
|
||||
|
||||
public function GetFields($entity)
|
||||
{
|
||||
|
@ -12,17 +12,17 @@ class UsersService extends BaseService
|
||||
'last_name' => $lastName,
|
||||
'password' => password_hash($password, PASSWORD_DEFAULT)
|
||||
));
|
||||
$newUserRow = $newUserRow->save();
|
||||
$permList = array();
|
||||
foreach ($this->getDatabase()->permission_hierarchy()->where('name', GROCY_DEFAULT_PERMISSIONS)->fetchAll() as $perm) {
|
||||
$permList[] = array(
|
||||
'user_id' => $newUserRow->id,
|
||||
'permission_id' => $perm->id
|
||||
);
|
||||
}
|
||||
$this->getDatabase()->user_permissions()->insert($permList);
|
||||
$newUserRow = $newUserRow->save();
|
||||
$permList = array();
|
||||
foreach ($this->getDatabase()->permission_hierarchy()->where('name', GROCY_DEFAULT_PERMISSIONS)->fetchAll() as $perm) {
|
||||
$permList[] = array(
|
||||
'user_id' => $newUserRow->id,
|
||||
'permission_id' => $perm->id
|
||||
);
|
||||
}
|
||||
$this->getDatabase()->user_permissions()->insert($permList);
|
||||
|
||||
return $newUserRow;
|
||||
return $newUserRow;
|
||||
}
|
||||
|
||||
public function EditUser(int $userId, string $username, string $firstName, string $lastName, string $password)
|
||||
|
@ -55,7 +55,7 @@
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<p class="small text-muted">
|
||||
|
@ -62,7 +62,7 @@
|
||||
@include('components.userfields_thead', array(
|
||||
'userfields' => $userfields
|
||||
))
|
||||
|
||||
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="d-none">
|
||||
|
@ -16,5 +16,5 @@
|
||||
<option value="{{ $shoppinglocation->id }}">{{ $shoppinglocation->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<div class="invalid-feedback">{{ $__t('You have to select a store') }}</div>
|
||||
<div class="invalid-feedback">{{ $__t('You have to select a store') }}</div>
|
||||
</div>
|
||||
|
@ -1,15 +1,15 @@
|
||||
<label>
|
||||
<input type="checkbox" name="{{ $perm->permission_name }}" class="permission-cb" data-perm-id="{{ $perm->permission_id }}" @if($perm->has_permission) checked @endif autocomplete="off">
|
||||
{{ $__t($perm->permission_name) }}
|
||||
<input type="checkbox" name="{{ $perm->permission_name }}" class="permission-cb" data-perm-id="{{ $perm->permission_id }}" @if($perm->has_permission) checked @endif autocomplete="off">
|
||||
{{ $__t($perm->permission_name) }}
|
||||
</label>
|
||||
<div id="permission-sub-{{ $perm->permission_name }}">
|
||||
<ul>
|
||||
@foreach($perm->uihelper_user_permissionsList(array('user_id' => $user->id))->via('parent') as $p)
|
||||
<li>
|
||||
@include('components.userpermission_select', array(
|
||||
'perm' => $p
|
||||
))
|
||||
</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
<ul>
|
||||
@foreach($perm->uihelper_user_permissionsList(array('user_id' => $user->id))->via('parent') as $p)
|
||||
<li>
|
||||
@include('components.userpermission_select', array(
|
||||
'perm' => $p
|
||||
))
|
||||
</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -33,7 +33,7 @@
|
||||
@include('components.userfields_thead', array(
|
||||
'userfields' => $userfields
|
||||
))
|
||||
|
||||
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="d-none">
|
||||
|
@ -3,9 +3,9 @@
|
||||
@section('title', $__t('Unauthorized'))
|
||||
|
||||
@section('content')
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="alert alert-danger">{{ $__t('You are not allowed to view this page') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="alert alert-danger">{{ $__t('You are not allowed to view this page') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
@stop
|
||||
|
@ -3,11 +3,11 @@
|
||||
@section('title', $__t('Page not found'))
|
||||
|
||||
@section('content')
|
||||
<meta http-equiv="refresh" content="5;url={{$U('/')}}">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="alert alert-danger">{{ $__t('This page does not exists') }}</div>
|
||||
<div>{{ $__t('You will be redirected to the default page in %s seconds', '5') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<meta http-equiv="refresh" content="5;url={{$U('/')}}">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="alert alert-danger">{{ $__t('This page does not exists') }}</div>
|
||||
<div>{{ $__t('You will be redirected to the default page in %s seconds', '5') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
@stop
|
||||
|
@ -3,9 +3,9 @@
|
||||
@section('title', $__t('Server error'))
|
||||
|
||||
@section('content')
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="alert alert-danger">{{ $__t('A server error occured while processing your request') }}</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="alert alert-danger">{{ $__t('A server error occured while processing your request') }}</div>
|
||||
<div class="alert alert-warning">
|
||||
{{ $__t('If you think this is a bug, please report it') }}<br>
|
||||
→ <a target="_blank" href="https://github.com/grocy/grocy/issues">https://github.com/grocy/grocy/issues</a>
|
||||
|
@ -1,20 +1,20 @@
|
||||
@extends('layout.default')
|
||||
|
||||
@section('content')
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div>
|
||||
<h6>{{ $__t('Error source') }}</h6>
|
||||
<pre><code>{!! $exception->getFile() !!}:{!! $exception->getLine() !!}</code></pre>
|
||||
</div>
|
||||
<div>
|
||||
<h6>{{ $__t('Error message') }}</h6>
|
||||
<pre><code>{!! $exception->getMessage() !!}</code></pre>
|
||||
</div>
|
||||
<div>
|
||||
<h6>{{ $__t('Stack trace') }}</h6>
|
||||
<pre><code>{!! $exception->getTraceAsString() !!}</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div>
|
||||
<h6>{{ $__t('Error source') }}</h6>
|
||||
<pre><code>{!! $exception->getFile() !!}:{!! $exception->getLine() !!}</code></pre>
|
||||
</div>
|
||||
<div>
|
||||
<h6>{{ $__t('Error message') }}</h6>
|
||||
<pre><code>{!! $exception->getMessage() !!}</code></pre>
|
||||
</div>
|
||||
<div>
|
||||
<h6>{{ $__t('Stack trace') }}</h6>
|
||||
<pre><code>{!! $exception->getTraceAsString() !!}</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@stop
|
||||
|
@ -28,7 +28,7 @@
|
||||
'additionalHtmlElements' => '<div id="inventory-change-info" class="form-text text-muted small d-none"></div>',
|
||||
'additionalHtmlContextHelp' => '<div id="tare-weight-handling-info" class="text-small text-info font-italic d-none">' . $__t('Tare weight handling enabled - please weigh the whole container, the amount to be posted will be automatically calculcated') . '</div>'
|
||||
))
|
||||
|
||||
|
||||
@php
|
||||
$additionalGroupCssClasses = '';
|
||||
if (!GROCY_FEATURE_FLAG_STOCK_BEST_BEFORE_DATE_TRACKING)
|
||||
|
@ -32,7 +32,7 @@
|
||||
<link href="{{ $U('/node_modules/datatables.net-responsive-bs4/css/responsive.bootstrap4.min.css?v=', true) }}{{ $version }}" rel="stylesheet">
|
||||
<link href="{{ $U('/node_modules/datatables.net-colreorder-bs4/css/colReorder.bootstrap4.min.css?v=', true) }}{{ $version }}" rel="stylesheet">
|
||||
<link href="{{ $U('/node_modules/datatables.net-select-bs4/css/select.bootstrap4.min.css?v=', true) }}{{ $version }}" rel="stylesheet">
|
||||
<link href="{{ $U('/node_modules/toastr/build/toastr.min.css?v=', true) }}{{ $version }}" rel="stylesheet">
|
||||
<link href="{{ $U('/node_modules/toastr/build/toastr.min.css?v=', true) }}{{ $version }}" rel="stylesheet">
|
||||
<link href="{{ $U('/node_modules/tempusdominus-bootstrap-4/build/css/tempusdominus-bootstrap-4.min.css?v=', true) }}{{ $version }}" rel="stylesheet">
|
||||
<link href="{{ $U('/node_modules/summernote/dist/summernote-bs4.css?v=', true) }}{{ $version }}" rel="stylesheet">
|
||||
<link href="{{ $U('/node_modules/bootstrap-select/dist/css/bootstrap-select.min.css?v=', true) }}{{ $version }}" rel="stylesheet">
|
||||
@ -79,7 +79,7 @@
|
||||
<span id="clock-small" class="d-inline d-sm-none"></span>
|
||||
<span id="clock-big" class="d-none d-sm-inline"></span>
|
||||
</span>
|
||||
|
||||
|
||||
<button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse" data-target="#sidebarResponsive">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
@ -161,7 +161,7 @@
|
||||
</a>
|
||||
</li>
|
||||
@endif
|
||||
|
||||
|
||||
@if(GROCY_FEATURE_FLAG_STOCK)
|
||||
<div class="nav-item-divider"></div>
|
||||
<li class="nav-item nav-item-sidebar permission-PRODUCT_PURCHASE" data-toggle="tooltip" data-placement="right" title="{{ $__t('Purchase') }}" data-nav-for-page="purchase">
|
||||
@ -221,7 +221,7 @@
|
||||
</li>
|
||||
@php if ($firstUserentity) { $firstUserentity = false; } @endphp
|
||||
@endforeach
|
||||
|
||||
|
||||
<div class="nav-item-divider"></div>
|
||||
<li class="nav-item nav-item-sidebar" data-toggle="tooltip" data-placement="right" title="{{ $__t('Manage master data') }}">
|
||||
<a class="nav-link nav-link-collapse collapsed discrete-link" data-toggle="collapse" href="#top-nav-manager-master-data">
|
||||
@ -480,7 +480,7 @@
|
||||
<script src="{{ $U('/js/grocy_nightmode.js?v=', true) }}{{ $version }}"></script>
|
||||
<script src="{{ $U('/js/grocy_clock.js?v=', true) }}{{ $version }}"></script>
|
||||
@stack('pageScripts')
|
||||
|
||||
|
||||
@php
|
||||
// @stack('componentScripts') maybe contains the components JS file reference multiple times
|
||||
// if the component was included more than once in the view
|
||||
|
@ -63,7 +63,7 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
@php $currentStockEntriesForLocation = FindAllObjectsInArrayByPropertyValue($currentStockLocationContent, 'location_id', $location->id); @endphp
|
||||
@foreach($currentStockEntriesForLocation as $currentStockEntry)
|
||||
@foreach($currentStockEntriesForLocation as $currentStockEntry)
|
||||
<tr>
|
||||
<td>
|
||||
{{ FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->name }}
|
||||
|
@ -18,7 +18,7 @@
|
||||
var fullcalendarEventSources = {!! json_encode(array($fullcalendarEventSources)) !!}
|
||||
var internalRecipes = {!! json_encode($internalRecipes) !!}
|
||||
var recipesResolved = {!! json_encode($recipesResolved) !!}
|
||||
|
||||
|
||||
Grocy.QuantityUnits = {!! json_encode($quantityUnits) !!};
|
||||
Grocy.QuantityUnitConversionsResolved = {!! json_encode($quantityUnitConversionsResolved) !!};
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
@if(file_exists(GROCY_DATAPATH . '/custom_css.html'))
|
||||
@php include GROCY_DATAPATH . '/custom_css.html' @endphp
|
||||
@endif
|
||||
|
||||
|
||||
<script>
|
||||
var Grocy = { };
|
||||
Grocy.OpenApi = { };
|
||||
|
@ -17,7 +17,7 @@
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-lg-6 col-xs-12">
|
||||
|
||||
|
||||
<h3 class="text-muted">{{ $__t('Barcode for product') }} <strong>{{ $product->name }}</strong></h3>
|
||||
|
||||
<script>Grocy.EditMode = '{{ $mode }}';</script>
|
||||
|
@ -17,7 +17,7 @@
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-lg-6 col-xs-12">
|
||||
|
||||
|
||||
@if($product != null)
|
||||
<h3 class="text-muted">{{ $__t('Override for product') }} <strong>{{ $product->name }}</strong></h3>
|
||||
@else
|
||||
|
@ -47,7 +47,7 @@
|
||||
<input type="text" class="form-control" required id="name" name="name" value="@if($mode == 'edit'){{ $recipe->name }}@endif">
|
||||
<div class="invalid-feedback">{{ $__t('A name is required') }}</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="form-group">
|
||||
<label for="recipe-picture">
|
||||
{{ $__t('Picture') }}
|
||||
@ -76,7 +76,7 @@
|
||||
'value' => $value,
|
||||
'invalidFeedback' => $__t('This cannot be lower than %s', '1'),
|
||||
'hint' => $__t('The ingredients listed here result in this amount of servings')
|
||||
))
|
||||
))
|
||||
|
||||
<div class="form-group">
|
||||
<div class="custom-control custom-checkbox">
|
||||
@ -85,7 +85,7 @@
|
||||
<label class="form-check-label custom-control-label" for="not_check_shoppinglist">
|
||||
{{ $__t('Do not check against the shopping list when adding missing items to it') }}
|
||||
<i class="fas fa-question-circle"
|
||||
data-toggle="tooltip"
|
||||
data-toggle="tooltip"
|
||||
title="{{ $__t('By default the amount to be added to the shopping list is `needed amount - stock amount - shopping list amount` - when this is enabled, it is only checked against the stock amount, not against what is already on the shopping list') }}"
|
||||
></i>
|
||||
</label>
|
||||
@ -142,7 +142,7 @@
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<table id="recipes-pos-table" class="table table-sm table-striped dt-responsive">
|
||||
<thead>
|
||||
<tr>
|
||||
|
@ -11,7 +11,7 @@
|
||||
</script>
|
||||
|
||||
<div class="row">
|
||||
|
||||
|
||||
<div class="col-xs-12 col-md-6 pb-3 d-print-none">
|
||||
<div>
|
||||
<h2 class="title">@yield('title')</h2>
|
||||
@ -172,28 +172,28 @@
|
||||
@endif
|
||||
<div class="card-body">
|
||||
<div class="shadow p-4 mb-5 bg-white rounded mt-n5 d-print-none @if(empty($recipe->picture_file_name)) d-none @endif">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<h3 class="card-title mb-0">{{ $recipe->name }}</h3>
|
||||
<div class="card-icons d-flex flex-wrap justify-content-end flex-shrink-1">
|
||||
<a class="recipe-consume hide-when-embedded @if(FindObjectInArrayByPropertyValue($recipesResolved, 'recipe_id', $recipe->id)->need_fulfilled == 0) disabled @endif"
|
||||
href="#"
|
||||
data-toggle="tooltip"
|
||||
title="{{ $__t('Consume all ingredients needed by this recipe') }}"
|
||||
data-recipe-id="{{ $recipe->id }}"
|
||||
<a class="recipe-consume hide-when-embedded @if(FindObjectInArrayByPropertyValue($recipesResolved, 'recipe_id', $recipe->id)->need_fulfilled == 0) disabled @endif"
|
||||
href="#"
|
||||
data-toggle="tooltip"
|
||||
title="{{ $__t('Consume all ingredients needed by this recipe') }}"
|
||||
data-recipe-id="{{ $recipe->id }}"
|
||||
data-recipe-name="{{ $recipe->name }}">
|
||||
<i class="fas fa-utensils"></i>
|
||||
</a>
|
||||
<a class="recipe-shopping-list hide-when-embedded @if(FindObjectInArrayByPropertyValue($recipesResolved, 'recipe_id', $recipe->id)->need_fulfilled_with_shopping_list == 1) disabled @endif"
|
||||
href="#"
|
||||
data-toggle="tooltip"
|
||||
title="{{ $__t('Put missing products on shopping list') }}"
|
||||
data-recipe-id="{{ $recipe->id }}"
|
||||
<a class="recipe-shopping-list hide-when-embedded @if(FindObjectInArrayByPropertyValue($recipesResolved, 'recipe_id', $recipe->id)->need_fulfilled_with_shopping_list == 1) disabled @endif"
|
||||
href="#"
|
||||
data-toggle="tooltip"
|
||||
title="{{ $__t('Put missing products on shopping list') }}"
|
||||
data-recipe-id="{{ $recipe->id }}"
|
||||
data-recipe-name="{{ $recipe->name }}">
|
||||
<i class="fas fa-cart-plus"></i>
|
||||
</a>
|
||||
<a class="recipe-fullscreen hide-when-embedded"
|
||||
href="#"
|
||||
data-toggle="tooltip"
|
||||
<a class="recipe-fullscreen hide-when-embedded"
|
||||
href="#"
|
||||
data-toggle="tooltip"
|
||||
title="{{ $__t('Expand to fullscreen') }}">
|
||||
<i class="fas fa-expand-arrows-alt"></i>
|
||||
</a>
|
||||
@ -207,25 +207,25 @@
|
||||
<div class="mb-4 @if(!empty($recipe->picture_file_name)) d-none @else d-flex @endif d-print-block justify-content-between align-items-center">
|
||||
<h1 class="card-title mb-0">{{ $recipe->name }}</h1>
|
||||
<div class="card-icons d-flex flex-wrap justify-content-end flex-shrink-1 d-print-none">
|
||||
<a class="recipe-consume hide-when-embedded @if(FindObjectInArrayByPropertyValue($recipesResolved, 'recipe_id', $recipe->id)->need_fulfilled == 0) disabled @endif"
|
||||
href="#"
|
||||
data-toggle="tooltip"
|
||||
title="{{ $__t('Consume all ingredients needed by this recipe') }}"
|
||||
data-recipe-id="{{ $recipe->id }}"
|
||||
<a class="recipe-consume hide-when-embedded @if(FindObjectInArrayByPropertyValue($recipesResolved, 'recipe_id', $recipe->id)->need_fulfilled == 0) disabled @endif"
|
||||
href="#"
|
||||
data-toggle="tooltip"
|
||||
title="{{ $__t('Consume all ingredients needed by this recipe') }}"
|
||||
data-recipe-id="{{ $recipe->id }}"
|
||||
data-recipe-name="{{ $recipe->name }}">
|
||||
<i class="fas fa-utensils"></i>
|
||||
</a>
|
||||
<a class="recipe-shopping-list hide-when-embedded @if(FindObjectInArrayByPropertyValue($recipesResolved, 'recipe_id', $recipe->id)->need_fulfilled_with_shopping_list == 1) disabled @endif"
|
||||
href="#"
|
||||
data-toggle="tooltip"
|
||||
title="{{ $__t('Put missing products on shopping list') }}"
|
||||
data-recipe-id="{{ $recipe->id }}"
|
||||
<a class="recipe-shopping-list hide-when-embedded @if(FindObjectInArrayByPropertyValue($recipesResolved, 'recipe_id', $recipe->id)->need_fulfilled_with_shopping_list == 1) disabled @endif"
|
||||
href="#"
|
||||
data-toggle="tooltip"
|
||||
title="{{ $__t('Put missing products on shopping list') }}"
|
||||
data-recipe-id="{{ $recipe->id }}"
|
||||
data-recipe-name="{{ $recipe->name }}">
|
||||
<i class="fas fa-cart-plus"></i>
|
||||
</a>
|
||||
<a class="recipe-fullscreen hide-when-embedded"
|
||||
href="#"
|
||||
data-toggle="tooltip"
|
||||
<a class="recipe-fullscreen hide-when-embedded"
|
||||
href="#"
|
||||
data-toggle="tooltip"
|
||||
title="{{ $__t('Expand to fullscreen') }}">
|
||||
<i class="fas fa-expand-arrows-alt"></i>
|
||||
</a>
|
||||
|
@ -14,7 +14,7 @@
|
||||
@section('content')
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h2 class="title">@yield('title')</h2>
|
||||
<h2 class="title">@yield('title')</h2>
|
||||
</div>
|
||||
<div class="col">
|
||||
@include('components.productpicker', array(
|
||||
|
@ -108,7 +108,7 @@
|
||||
@else
|
||||
<input type="hidden" name="location_id" id="location_id" value="1">
|
||||
@endif
|
||||
|
||||
|
||||
@include('components.datetimepicker2', array(
|
||||
'id' => 'purchase_date',
|
||||
'initialValue' => $stockEntry->purchased_date,
|
||||
|
@ -114,7 +114,7 @@
|
||||
@include('components.userfields_thead', array(
|
||||
'userfields' => $userfields
|
||||
))
|
||||
|
||||
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="d-none">
|
||||
|
@ -56,7 +56,7 @@
|
||||
<option></option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
||||
@php /*@include('components.locationpicker', array(
|
||||
'locations' => $locations,
|
||||
'isRequired' => true,
|
||||
@ -75,7 +75,7 @@
|
||||
</div>
|
||||
|
||||
<button id="save-transfer-button" class="btn btn-success">{{ $__t('OK') }}</button>
|
||||
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
||||
|
@ -5,9 +5,9 @@
|
||||
@section('viewJsName', 'userpermissions')
|
||||
|
||||
@push('pageScripts')
|
||||
<script>
|
||||
Grocy.EditObjectId = {{ $user->id }};
|
||||
</script>
|
||||
<script>
|
||||
Grocy.EditObjectId = {{ $user->id }};
|
||||
</script>
|
||||
@endpush
|
||||
|
||||
@section('content')
|
||||
@ -20,15 +20,15 @@
|
||||
<div class="row mt-3">
|
||||
<div class="col">
|
||||
<ul>
|
||||
@foreach($permissions as $perm)
|
||||
<li>
|
||||
@include('components.userpermission_select', array(
|
||||
'permission' => $perm
|
||||
))
|
||||
</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
<button id="permission-save" class="btn btn-success" type="submit">{{ $__t('Save') }}</button>
|
||||
@foreach($permissions as $perm)
|
||||
<li>
|
||||
@include('components.userpermission_select', array(
|
||||
'permission' => $perm
|
||||
))
|
||||
</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
<button id="permission-save" class="btn btn-success" type="submit">{{ $__t('Save') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
Loading…
x
Reference in New Issue
Block a user