Skip to content

Commit

Permalink
Merge pull request #2811 from Leantime/apiFixes
Browse files Browse the repository at this point in the history
Api fixes
  • Loading branch information
marcelfolaron authored Nov 22, 2024
2 parents 9f449be + 5fd0a9e commit 9beb2b0
Show file tree
Hide file tree
Showing 25 changed files with 437 additions and 57 deletions.
2 changes: 1 addition & 1 deletion .dev/docker-compose.tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ services:
- "44302:443" #Using different ports for testing, so we don't have to worry about collision (available range is 44300–44399)
environment:
LEAN_DB_HOST: 'db'
LEAN_DB_USER: 'leantime'
LEAN_DB_USER: 'root'
LEAN_DB_PASSWORD: 'leantime'
LEAN_DB_DATABASE: 'leantime_test'
LEAN_DB_PORT: '3306'
Expand Down
4 changes: 2 additions & 2 deletions .dev/test.env
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ LEAN_APP_DIR = '' # Base of application without trai
LEAN_DEBUG = 1 # Debug flag

# Database
LEAN_DB_HOST='localhost' # Database host
LEAN_DB_HOST='db' # Database host
LEAN_DB_USER='root' # Database username
LEAN_DB_PASSWORD='test' # Database password
LEAN_DB_DATABASE='leantime' # Database name
LEAN_DB_DATABASE='leantime_test' # Database name
LEAN_DB_PORT='3306' # Database port

## Optional Configuraiton, you may ommit these from your .env file
Expand Down
2 changes: 0 additions & 2 deletions .idea/leantime-oss.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,21 @@ The dev environment provides a MySQL server, mail server, s3 server, and should
Additionally, Xdebug is enabled, but you will have to modify your
IDE key in the ``.dev/xdebug.ini`` file(or alternatively, on your IDE). You also need to have port 9003 temporarily open on your firewall so you can utilize it effectively. This is because connections from docker to the host will count as external inbound connections
<br /><br />

### Run Tests

Static Analysis `make phpstan`<br />
Code Style `make test-code-style` (to fix code style automatically use `make fix-code-style`)<br />
Unit Tests `make unit-test`<br />
Acceptance Tests `make acceptance-test`<br /> (requires docker)

You can test individual acceptance test groups directly using:<br />
For api: <br />
`docker compose --file .dev/docker-compose.yaml --file .dev/docker-compose.tests.yaml exec leantime-dev php vendor/bin/codecept run -g api --steps`<br />
For timesheets: <br />
`docker compose --file .dev/docker-compose.yaml --file .dev/docker-compose.tests.yaml exec leantime-dev php vendor/bin/codecept run -g timesheet --steps`<br />


### 🏗 Update ###

#### Manual
Expand Down
2 changes: 0 additions & 2 deletions app/Core/Db/Db.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,6 @@ public function __construct($connection = 'mysql')
} catch (\PDOException $e) {

Log::error("Can't connect to database");
Log::error($e);

throw new \Exception($e);
}
}
Expand Down
2 changes: 1 addition & 1 deletion app/Core/Http/ApiRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public function getAuthorizationHeader(): string
*/
public function getAPIKey(): string
{
return $this->headers->get('x-api-key');
return $this->headers->get('x-api-key') ?? '';
}

/**
Expand Down
13 changes: 8 additions & 5 deletions app/Core/Http/HttpKernel.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,8 @@ class HttpKernel extends Kernel
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\Leantime\Core\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
\Leantime\Core\Middleware\Auth::class,
\Leantime\Core\Middleware\ApiAuth::class,
\Leantime\Core\Middleware\SetCacheHeaders::class,
\Leantime\Core\Middleware\Localization::class,
\Leantime\Core\Middleware\CurrentProject::class,
\Leantime\Core\Middleware\LoadPlugins::class,
];

Expand All @@ -57,15 +54,13 @@ class HttpKernel extends Kernel
protected $middlewareGroups = [
'web' => [
\Leantime\Core\Middleware\Auth::class,
\Leantime\Core\Middleware\Localization::class,
\Leantime\Core\Middleware\CurrentProject::class,
],
'api' => [
\Leantime\Core\Middleware\ApiAuth::class,
],
'hx' => [
\Leantime\Core\Middleware\Auth::class,
\Leantime\Core\Middleware\Localization::class,
\Leantime\Core\Middleware\CurrentProject::class,
],
];
Expand Down Expand Up @@ -103,6 +98,14 @@ protected function sendRequestThroughRouter($request)
//Can savely assume events are available here.
self::dispatch_event('request_started', ['request' => $request]);

if ($request instanceof ApiRequest) {

array_splice($this->middleware, 5, 0, $this->middlewareGroups['api']);

} else {
array_splice($this->middleware, 5, 0, $this->middlewareGroups['web']);
}

//This filter only works for system plugins
//Regular plugins are not available until after install verification
$this->middleware = self::dispatch_filter('middleware', $this->middleware, ['request' => $request]);
Expand Down
6 changes: 5 additions & 1 deletion app/Core/Http/IncomingRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ public static function capture()
//static::$httpMethodParameterOverride = false;
//parent::enableHttpMethodParameterOverride();

//static::enableHttpMethodParameterOverride();

$headers = collect(getallheaders())
->mapWithKeys(fn ($val, $key) => [
strtolower($key) => match (true) {
Expand All @@ -66,9 +68,11 @@ public static function capture()
])
->all();

$requestUriTest = strtolower($_SERVER['REQUEST_URI'] ?? '');

$request = match (true) {
isset($headers['hx-request']) => HtmxRequest::createFromGlobals(),
isset($headers['x-api-key']) => ApiRequest::createFromGlobals(),
(isset($headers['x-api-key']) || str_starts_with($requestUriTest, '/api/jsonrpc')) => ApiRequest::createFromGlobals(),
defined('LEAN_CLI') && LEAN_CLI => CliRequest::createFromGlobals(),
default => parent::createFromGlobals(),
};
Expand Down
6 changes: 5 additions & 1 deletion app/Core/Middleware/ApiAuth.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,11 @@ public function handle(IncomingRequest $request, Closure $next): Response
self::dispatchEvent('before_api_request', ['application' => app()]);

$apiKey = $request->getAPIKey();
$apiUser = app()->make(ApiService::class)->getAPIKeyUser($apiKey);
$apiUser = false;

if ($apiKey !== null) {
$apiUser = app()->make(ApiService::class)->getAPIKeyUser($apiKey);
}

if (! $apiUser) {
return new Response(json_encode(['error' => 'Invalid API Key']), 401);
Expand Down
12 changes: 8 additions & 4 deletions app/Domain/Api/Controllers/Jsonrpc.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@ class Jsonrpc extends Controller
*/
public function init(): void
{
if ($_SERVER['REQUEST_METHOD'] === 'POST' && empty($_POST)) {
$this->json_data = json_decode(file_get_contents('php://input'), JSON_OBJECT_AS_ARRAY);
if ($this->incomingRequest->server('REQUEST_METHOD') === 'POST' && empty($_POST)) {
$bodyContent = json_decode($this->incomingRequest->getContent(), JSON_OBJECT_AS_ARRAY);
$this->json_data = $bodyContent ?? '';
}
}

Expand All @@ -41,7 +42,7 @@ public function init(): void
*/
public function post(array $params): Response
{
if (empty($params)) {
if (empty($params) || isset($params['act'])) {
$params = $this->json_data;
}

Expand Down Expand Up @@ -129,8 +130,11 @@ private function executeApiRequest(array $params): Response
* @see https://jsonrpc.org/specification#batch
*/
if (array_keys($params) == range(0, count($params) - 1)) {

return $this->tpl->displayJson(array_map(
fn ($requestParams) => json_decode($this->executeApiRequest($requestParams)->getContent()),
function ($requestParams) {
return json_decode($this->executeApiRequest($requestParams)->getContent());
},
$params
));
}
Expand Down
9 changes: 6 additions & 3 deletions app/Domain/Comments/Repositories/Comments.php
Original file line number Diff line number Diff line change
Expand Up @@ -204,16 +204,19 @@ public function getAllAccountComments(?int $projectId, ?int $moduleId): array|fa
comment.moduleId,
comment.userId,
comment.commentParent,
comment.status
comment.status,
zp_projects.id AS projectId
FROM zp_comment as comment
LEFT JOIN zp_tickets ON comment.moduleId = zp_tickets.id
LEFT JOIN zp_canvas_items ON comment.moduleId = zp_tickets.id
LEFT JOIN zp_canvas ON zp_canvas.id = zp_canvas_items.canvasId
LEFT JOIN zp_projects ON zp_canvas.projectId = zp_projects.id OR zp_tickets.projectId = zp_projects.id
WHERE zp_projects.id IN (SELECT projectId FROM zp_relationuserproject WHERE zp_relationuserproject.userId = :userId)
WHERE
(zp_projects.id IN (SELECT projectId FROM zp_relationuserproject WHERE zp_relationuserproject.userId = :userId)
OR zp_projects.psettings = 'all'
OR (zp_projects.psettings = 'client' AND zp_projects.clientId = :clientId)
OR (:requesterRole = 'admin' OR :requesterRole = 'manager') ";
OR (:requesterRole = 'admin' OR :requesterRole = 'manager')) ";

if (isset($projectId) && $projectId > 0) {
$sql .= ' AND (zp_projects.id = :projectId)';
Expand Down
37 changes: 21 additions & 16 deletions app/Language/de-DE.ini
Original file line number Diff line number Diff line change
Expand Up @@ -2402,22 +2402,27 @@ menu.customfields_premium="<span class='fas fa-fw fa-list'></span> Custom Fields
menu.whiteboards_premium="<span class='fas fa-fw fa-draw-polygon'></span> Whiteboards <span class='label label-primary feature-label'>Premium</span>"

#3.0.7=
input.placeholders.jobtitle="Job Title"

headlines.your_account="Your Account"
text.welcome_to_leantime_2="Hi There, 👋 <br />We're excited to see you! We just need a little more information to get your account ready for you."
text.things_get_organized="Things are about to get more organized!"
text.project_hub_intro="This is your project hub. All the projects you are currently assigned to or have favorited are here."
text.no_favorites="You don't have any favorites. 😿"
text.all_assigned_projects="🗂️ All Assigned Projects"
text.get_organized_with_projects="We're excited to show you around and get your work organized.<br /><br />Leantime manages your work in \"projects\". The easiest way to define a project is to think about something <strong>you would like to accomplish</strong>. This can include metrics you'd like to reach, a client project or something you would like to create. Projects are then broken down into Goals with metrics and Milestones. <br /><br />"
label.start_with_project_title="Let's start by giving your project a title"
headlines.make_it_happen="Make it happen"

text.structured_project_thinking="Accomplishing your goals and staying focused requires you to define a foundation for your project. All too often we just 'brain dump' the latest priorities without questioning whether they wiil move the needle for us. Let's ask ourselves a few simple questions to get a better understanding of what we are working towards."
label.what_are_you_trying_to_accomplish="What are you trying to accomplish?"
label.how_does_the_world_look_like="What does the world, your business or your customers journey look like when you're done?"
label.why_is_this_important="Why is this important?"
input.placeholders.jobtitle="Jobtitel"

headlines.your_account="Dein Account"
text.welcome_to_leantime_2="Hallo, 👋 <br />Wir freuen uns, Dich zu sehen! Wir brauchen nur noch ein paar Informationen, um Dein Konto für Dich vorzubereiten."
text.things_get_organized="Die Dinge werden bald besser organisiert!"
text.project_hub_intro="Dies ist Dein Projekt-Hub. Alle Projekte, die Dir derzeit zugewiesen sind oder die Du als Favoriten markiert hast, findest Du hier."
text.no_favorites="Du hast keine Favoriten. 😿"
text.all_assigned_projects="🗂️ Alle zugewiesenen Projekte"
text.get_organized_with_projects="Wir freuen uns, Dir alles zu zeigen und Deine Arbeit zu organisieren.<br /><br />Leantime verwaltet Deine Arbeit in \"Projekten\". Der einfachste Weg, ein Projekt zu definieren, besteht darin, über etwas nachzudenken, <strong>das Du erreichen möchtest</strong>. Dies kann Kennzahlen umfassen, die Du erreichen möchtest, ein Kundenprojekt oder etwas, das Du erstellen möchtest. Projekte werden dann in Ziele mit Kennzahlen und Meilensteinen unterteilt. <br /><br />"
label.start_with_project_title="Beginnen wir damit, Deinem Projekt einen Titel zu geben"
headlines.make_it_happen="Mach es wahr"

text.structured_project_thinking="Um Deine Ziele zu erreichen und konzentriert zu bleiben, musst du eine Grundlage für Ihr Projekt definieren. Allzu oft werfen wir die neuesten Prioritäten einfach aus dem Kopf, ohne uns zu fragen, ob sie uns weiterbringen. Stellen wir uns ein paar einfache Fragen, um besser zu verstehen, worauf wir hinarbeiten"
label.what_are_you_trying_to_accomplish="Was versuchst Du zu erreichen?"
label.how_does_the_world_look_like="Wie sieht die Welt, Dein Unternehmen oder die Customer Journey aus, wenn Du fertig bist?"
label.why_is_this_important="Warum ist dies wichtig?"

#3.0.8=
text.ical_title="Leantime Kalender"
text.ical.todo_is_due="Eine Leantime Aufgabe ist bald fällig."
text.ical.todo_start_alert="Eine Leantime Aufgabe ist für die baldige Bearbeitung angesetzt"

#3.0.8=
text.ical_title="Leantime Calendar"
Expand Down
1 change: 1 addition & 0 deletions app/Language/en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -2584,3 +2584,4 @@ widget.descriptions.implementation_intentions = "Daily Intentions are a strategy
titles.account_details = "😀 Setting Account Details"
titles.determine_visual_experience = "👀 Determining A Visual Experience"
text.choose_a_theme_and_font_easy_to_read = "You can choose a theme and font that is easy on your brain."

4 changes: 0 additions & 4 deletions codeception.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ paths:
output: tests/_output
data: tests/Support/Data
support: tests/Support
envs: tests/_envs
log: tests/_log
actor_suffix: Tester
extensions:
enabled:
Expand All @@ -21,5 +19,3 @@ coverage:
include:
- app/*

params:
- tests/_envs/.env.test
16 changes: 11 additions & 5 deletions makefile
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,10 @@ package: clean build
# Removing unneeded items for release
rm -rf $(TARGET_DIR)/public/dist/images/Screenshots

# Removing js directories
# Removing javascript directories
find $(TARGET_DIR)/app/Domain/ -depth -maxdepth 2 -name "js" -exec rm -rf {} \;

# Removing un-compiled js files
# Removing un-compiled javascript files
find $(TARGET_DIR)/public/dist/js/ -depth -mindepth 1 ! -name "*compiled*" -exec rm -rf {} \;

#create zip files
Expand Down Expand Up @@ -107,12 +107,19 @@ run-dev: build-dev

acceptance-test: build-dev
docker compose --file .dev/docker-compose.yaml --file .dev/docker-compose.tests.yaml up --detach --build --remove-orphans
docker compose --file .dev/docker-compose.yaml --file .dev/docker-compose.tests.yaml exec leantime-dev php vendor/bin/codecept run Acceptance -vvv
docker compose --file .dev/docker-compose.yaml --file .dev/docker-compose.tests.yaml exec leantime-dev php vendor/bin/codecept clean
docker compose --file .dev/docker-compose.yaml --file .dev/docker-compose.tests.yaml exec leantime-dev php vendor/bin/codecept build
docker compose --file .dev/docker-compose.yaml --file .dev/docker-compose.tests.yaml exec leantime-dev php vendor/bin/codecept run Acceptance --steps

unit-test: build-dev
docker compose --file .dev/docker-compose.yaml --file .dev/docker-compose.tests.yaml up --detach --build --remove-orphans
docker compose --file .dev/docker-compose.yaml --file .dev/docker-compose.tests.yaml exec leantime-dev php vendor/bin/codecept build
docker compose --file .dev/docker-compose.yaml --file .dev/docker-compose.tests.yaml exec leantime-dev php vendor/bin/codecept run Unit -vv
docker compose --file .dev/docker-compose.yaml --file .dev/docker-compose.tests.yaml exec leantime-dev php vendor/bin/codecept run Unit --steps

api-test: build-dev
docker compose --file .dev/docker-compose.yaml --file .dev/docker-compose.tests.yaml up --detach --build --remove-orphans
docker compose --file .dev/docker-compose.yaml --file .dev/docker-compose.tests.yaml exec leantime-dev php vendor/bin/codecept build
docker compose --file .dev/docker-compose.yaml --file .dev/docker-compose.tests.yaml exec leantime-dev php vendor/bin/codecept run Api --steps

acceptance-test-ci: build-dev
docker compose --file .dev/docker-compose.yaml --file .dev/docker-compose.tests.yaml up --detach --build --remove-orphans
Expand Down Expand Up @@ -148,4 +155,3 @@ clear-cache:
rm -rf ./storage/framework/views/*.php

.PHONY: install-deps build-js build package clean run-dev

6 changes: 4 additions & 2 deletions tests/Acceptance.suite.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ bootstrap: bootstrap.php
modules:
enabled:
- \Tests\Support\Helper\Acceptance
- REST:
url: 'https://leantime-dev'
depends: PhpBrowser
- WebDriver:
url: 'https://leantime-dev'
host: selenium
Expand All @@ -19,10 +22,9 @@ modules:
acceptInsecureCerts: true
goog:chromeOptions:
args: [ "--headless" ]

- Db:
dsn: "mysql:host=db;port=3306;dbname=leantime_test"
user: leantime
user: root
password: leantime
populate: true
cleanup: true
Expand Down
Loading

0 comments on commit 9beb2b0

Please sign in to comment.