Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ body:
label: Версия DLE
options:
- "20.0"
- "19.x"
- "18.x"
- "17.x"
- "16.x"
validations:
Expand Down
47 changes: 3 additions & 44 deletions .github/workflows/composer-check.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<<<<<<< New base: Update README.md
name: Composer check

on:
workflow_dispatch:
pull_request:
paths:
- 'upload/api/composer.json'
Expand Down Expand Up @@ -33,52 +33,11 @@ jobs:
run: composer validate --no-check-publish --strict

- name: Install dependencies
run: composer install --no-dev --no-interaction --prefer-dist --no-progress

- name: PHP syntax smoke
run: |
find . -name '*.php' -not -path './vendor/*' -print0 \
| xargs -0 -n1 php -l
|||||||
=======
name: Composer check

on:
pull_request:
paths:
- 'upload/api/composer.json'
- 'upload/api/composer.lock'
- 'upload/api/**/*.php'
- '.github/workflows/composer-check.yml'
push:
paths:
- 'upload/api/composer.json'
- 'upload/api/composer.lock'

jobs:
composer:
runs-on: ubuntu-latest
defaults:
run:
working-directory: upload/api
steps:
- uses: actions/checkout@v4

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.3'
extensions: json, pdo, simplexml
coverage: none

- name: Validate composer.json
run: composer validate --no-check-publish --strict

- name: Install dependencies
run: composer install --no-interaction --prefer-dist --no-progress
rm -rf vendor
composer install --no-dev --no-interaction --prefer-dist --no-progress

- name: PHP syntax smoke
run: |
find . -name '*.php' -not -path './vendor/*' -print0 \
| xargs -0 -n1 php -l
>>>>>>> Current commit: Начало обновления до api v2
4 changes: 3 additions & 1 deletion .github/workflows/composer-update.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ jobs:
coverage: none

- name: Run composer update
run: composer update --no-dev --no-interaction --prefer-dist --no-progress
run: |
rm -rf vendor
composer update --no-dev --no-interaction --prefer-dist --no-progress

- name: Open PR if lock file changed
uses: peter-evans/create-pull-request@v8
Expand Down
33 changes: 1 addition & 32 deletions .github/workflows/dependabot-auto-merge.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<<<<<<< New base: Update README.md
name: Dependabot auto-merge

on:
pull_request:
workflow_dispatch:

permissions:
contents: write
Expand All @@ -27,34 +27,3 @@ jobs:
env:
PR_URL: ${{ github.event.pull_request.html_url }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|||||||
=======
name: Dependabot auto-merge

on:
pull_request:

permissions:
contents: write
pull-requests: write

jobs:
dependabot:
runs-on: ubuntu-latest
if: github.event.pull_request.user.login == 'dependabot[bot]'
steps:
- name: Dependabot metadata
id: metadata
uses: dependabot/fetch-metadata@v2
with:
github-token: ${{ secrets.GITHUB_TOKEN }}

- name: Enable auto-merge for patch and minor
if: |
steps.metadata.outputs.update-type == 'version-update:semver-patch' ||
steps.metadata.outputs.update-type == 'version-update:semver-minor'
run: gh pr merge --auto --squash "$PR_URL"
env:
PR_URL: ${{ github.event.pull_request.html_url }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
>>>>>>> Current commit: Начало обновления до api v2
4 changes: 3 additions & 1 deletion .github/workflows/openapi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ jobs:
coverage: none

- name: Install dependencies
run: composer install --no-dev --no-interaction --prefer-dist --no-progress
run: |
rm -rf vendor
composer install --no-dev --no-interaction --prefer-dist --no-progress

- name: Generate openapi.yaml
run: composer openapi
Expand Down
28 changes: 0 additions & 28 deletions upload/api/src/Http/V2/Controller/MeController.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
<<<<<<< New base: Update README.md
<?php

declare(strict_types=1);
Expand All @@ -23,30 +22,3 @@ public function me(Request $request, Response $_response): Response {
}

}
|||||||
=======
<?php

declare(strict_types=1);

namespace DleApi\Http\V2\Controller;

use DleApi\Http\V2\JsonResponder;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;

/**
* GET /me и OAuth userinfo — субъект AuthToken.
*/
final class MeController {

public function __construct(
private readonly MePayloadBuilder $payloadBuilder = new MePayloadBuilder(),
) {}

public function me(Request $request, Response $_response): Response {
return JsonResponder::ok($this->payloadBuilder->fromRequest($request));
}

}
>>>>>>> Current commit: Начало обновления до api v2
173 changes: 0 additions & 173 deletions upload/api/src/Http/V2/Controller/OauthController.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
<<<<<<< New base: Update README.md
<?php

declare(strict_types=1);
Expand Down Expand Up @@ -168,175 +167,3 @@ private function apiBaseUrl(): string {
}

}
|||||||
=======
<?php

declare(strict_types=1);

namespace DleApi\Http\V2\Controller;

use DleApi\Http\V2\JsonResponder;
use DleApi\Http\V2\OAuth\TokenService;
use DevCraft\Modules\DleApi\Services\DleApiConfig;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;

/**
* OAuth token / revoke / authorize / discovery / userinfo.
*/
final class OauthController {

public function __construct(
private readonly TokenService $tokens = new TokenService(),
) {
}

public function token(Request $request, Response $_response): Response {
$params = array_merge($request->getQueryParams(), (array) $request->getParsedBody());
$cred = (string) ($params['credential_type'] ?? '');
$grant = (string) ($params['grant_type'] ?? '');

if($cred !== '') {
$result = match ($cred) {
'api_key' => $this->tokens->issueByApiKey(
(string) ($params['api_key'] ?? ''),
(string) ($params['scope'] ?? ''),
),
'auth' => $this->tokens->issueByAuth(
(string) ($params['username'] ?? ''),
(string) ($params['password'] ?? ''),
(string) ($params['scope'] ?? ''),
),
'oauth_client' => $this->tokens->issueByOauthClient(
(string) ($params['client_id'] ?? ''),
(string) ($params['client_secret'] ?? ''),
(string) ($params['scope'] ?? ''),
),
default => ['error' => 'unsupported_credential_type', 'message' => __('Неподдерживаемый credential_type')],
};
} else {
$result = match ($grant) {
'client_credentials' => $this->tokens->issueByOauthClient(
(string) ($params['client_id'] ?? ''),
(string) ($params['client_secret'] ?? ''),
(string) ($params['scope'] ?? ''),
),
'authorization_code' => $this->tokens->issueAuthorizationCode(
(string) ($params['client_id'] ?? ''),
(string) ($params['client_secret'] ?? ''),
(string) ($params['code'] ?? ''),
(string) ($params['redirect_uri'] ?? ''),
(string) ($params['code_verifier'] ?? ''),
),
'refresh_token' => $this->tokens->refresh((string) ($params['refresh_token'] ?? '')),
'password' => $this->tokens->issuePassword(
(string) ($params['client_id'] ?? ''),
(string) ($params['client_secret'] ?? ''),
(string) ($params['username'] ?? ''),
(string) ($params['password'] ?? ''),
(string) ($params['scope'] ?? ''),
),
default => ['error' => 'unsupported_grant_type', 'message' => __('Укажите credential_type или grant_type')],
};
}

$status = isset($result['error']) ? 400 : 200;

return JsonResponder::ok($result, $status);
}

public function revoke(Request $request, Response $_response): Response {
$body = (array) $request->getParsedBody();
$this->tokens->revoke((string) ($body['token'] ?? ''));

return JsonResponder::ok(['revoked' => true]);
}

public function authorize(Request $request, Response $response): Response {
$q = array_merge($request->getQueryParams(), (array) $request->getParsedBody());
$clientId = (string) ($q['client_id'] ?? '');
$redirect = (string) ($q['redirect_uri'] ?? '');
$state = (string) ($q['state'] ?? '');
$challenge = (string) ($q['code_challenge'] ?? '');
$method = (string) ($q['code_challenge_method'] ?? 'S256');

global $is_logged, $member_id, $config;
$userId = 0;
if(!empty($is_logged) && is_array($member_id ?? null)) {
$userId = (int) ($member_id['user_id'] ?? 0);
}

if($clientId === '' || $redirect === '') {
return JsonResponder::error('invalid_request', __('Нужны client_id и redirect_uri'), 400);
}

$authErr = $this->tokens->validateAuthorizeRequest($clientId, $redirect);
if($authErr !== null) {
return JsonResponder::error($authErr['error'], $authErr['message'], 400);
}

if($userId < 1) {
$return = (string) $request->getUri();
if(session_status() === PHP_SESSION_ACTIVE || @session_start()) {
$_SESSION['dleapi_oauth_return'] = $return;
}
$login = rtrim((string) ($config['http_home_url'] ?? '/'), '/') . '/index.php?do=login';

return $response->withHeader('Location', $login)->withStatus(302);
}

$sep = str_contains($redirect, '?') ? '&' : '?';
if(DleApiConfig::isDemoMode()) {
$loc = $redirect . $sep . http_build_query(array_filter([
'error' => 'demo_mode',
'error_description' => __('Авторизация пройдена, но сброшена в демо-режиме'),
'authorized' => '1',
'demo_mode' => '1',
'state' => $state ?: null,
]));

return $response->withHeader('Location', $loc)->withStatus(302);
}

$code = $this->tokens->createAuthCode($clientId, $userId, $redirect, (string) ($q['scope'] ?? ''), $challenge, $method);
$loc = $redirect . $sep . http_build_query(array_filter(['code' => $code, 'state' => $state ?: null]));

return $response->withHeader('Location', $loc)->withStatus(302);
}

public function discovery(Request $_request, Response $_response): Response {
$base = $this->apiBaseUrl();

return JsonResponder::ok([
'issuer' => $base,
'authorization_endpoint' => $base . '/oauth/authorize',
'token_endpoint' => $base . '/oauth/token',
'revocation_endpoint' => $base . '/oauth/revoke',
'userinfo_endpoint' => $base . '/oauth/userinfo',
'response_types_supported' => ['code'],
'grant_types_supported' => [
'authorization_code',
'refresh_token',
'client_credentials',
'password',
],
'code_challenge_methods_supported' => ['S256', 'plain'],
'token_endpoint_auth_methods_supported' => ['client_secret_post', 'client_secret_basic'],
'credential_types_supported' => ['api_key', 'auth', 'oauth_client'],
]);
}

public function userinfo(Request $request, Response $_response): Response {
return (new MeController())->me($request, $_response);
}

private function apiBaseUrl(): string {
global $config;
$host = rtrim((string) ($config['http_home_url'] ?? ''), '/');

return $host . '/api/v2';
}

}
>>>>>>> Current commit: Начало обновления до api v2
Loading