mirror of
https://github.com/maelgangloff/domain-watchdog.git
synced 2025-12-29 16:15:04 +00:00
feat: add instance config endpoint
This commit is contained in:
5
.env
5
.env
@@ -38,7 +38,6 @@ MESSENGER_TRANSPORT_DSN=doctrine://default?auto_setup=0
|
|||||||
|
|
||||||
###> symfony/mailer ###
|
###> symfony/mailer ###
|
||||||
# MAILER_DSN=null://null
|
# MAILER_DSN=null://null
|
||||||
MAILER_SENDER_EMAIL=notifications@example.com
|
|
||||||
###< symfony/mailer ###
|
###< symfony/mailer ###
|
||||||
|
|
||||||
###> nelmio/cors-bundle ###
|
###> nelmio/cors-bundle ###
|
||||||
@@ -57,6 +56,10 @@ JWT_PASSPHRASE=827c9f8cce8bb82e75b2aec4a14a61f572ac28c7a8531f08dcdf1652573a7049
|
|||||||
LOCK_DSN=flock
|
LOCK_DSN=flock
|
||||||
###< symfony/lock ###
|
###< symfony/lock ###
|
||||||
|
|
||||||
|
|
||||||
|
MAILER_SENDER_EMAIL=notifications@example.com
|
||||||
|
LIMITED_FEATURES=false
|
||||||
|
OAUTH_ENABLED=false
|
||||||
OAUTH_CLIENT_ID=
|
OAUTH_CLIENT_ID=
|
||||||
OAUTH_CLIENT_SECRET=
|
OAUTH_CLIENT_SECRET=
|
||||||
OAUTH_AUTHORIZATION_URL=
|
OAUTH_AUTHORIZATION_URL=
|
||||||
|
|||||||
@@ -54,4 +54,4 @@ Contributions are welcome as long as they do not contravene the Code of Conduct.
|
|||||||
|
|
||||||
[^1]: RFC 3912 : WHOIS Protocol Specification. (2004). IETF Datatracker. https://datatracker.ietf.org/doc/html/rfc3912
|
[^1]: RFC 3912 : WHOIS Protocol Specification. (2004). IETF Datatracker. https://datatracker.ietf.org/doc/html/rfc3912
|
||||||
[^2]: 2023 Global Amendments to the Base gTLD Registry Agreement (RA), Specification 13, and 2013 Registrar
|
[^2]: 2023 Global Amendments to the Base gTLD Registry Agreement (RA), Specification 13, and 2013 Registrar
|
||||||
Accreditation Agreement (RAA) - ICANN. (s. d.). https://www.icann.org/resources/pages/global-amendment-2023-en
|
Accreditation Agreement (RAA) - ICANN. (2023). https://www.icann.org/resources/pages/global-amendment-2023-en
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ export default function App() {
|
|||||||
if (location.pathname === '/login') navigate('/home')
|
if (location.pathname === '/login') navigate('/home')
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
setIsAuthenticated(false)
|
setIsAuthenticated(false)
|
||||||
navigate('/home')
|
if (location.pathname !== '/login') navigate('/home')
|
||||||
})
|
})
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React, {createContext, useContext, useEffect, useState} from "react";
|
import React, {createContext, useContext, useEffect, useState} from "react";
|
||||||
import {Alert, Button, Card, Flex, Form, Input} from "antd";
|
import {Alert, Button, Card, Flex, Form, Input} from "antd";
|
||||||
import {getUser, login} from "../utils/api";
|
import {getConfiguration, getUser, InstanceConfig, login} from "../utils/api";
|
||||||
import {useNavigate} from "react-router-dom";
|
import {useNavigate} from "react-router-dom";
|
||||||
import {t} from 'ttag'
|
import {t} from 'ttag'
|
||||||
|
|
||||||
@@ -13,7 +13,8 @@ export const AuthenticatedContext = createContext<any>(null)
|
|||||||
|
|
||||||
export default function LoginPage() {
|
export default function LoginPage() {
|
||||||
|
|
||||||
const [error, setError] = useState()
|
const [error, setError] = useState<string>()
|
||||||
|
const [configuration, setConfiguration] = useState<InstanceConfig>()
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const {setIsAuthenticated} = useContext(AuthenticatedContext)
|
const {setIsAuthenticated} = useContext(AuthenticatedContext)
|
||||||
|
|
||||||
@@ -32,6 +33,7 @@ export default function LoginPage() {
|
|||||||
setIsAuthenticated(true)
|
setIsAuthenticated(true)
|
||||||
navigate('/home')
|
navigate('/home')
|
||||||
})
|
})
|
||||||
|
getConfiguration().then(setConfiguration)
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
return <Flex gap="middle" align="center" justify="center" vertical><Card
|
return <Flex gap="middle" align="center" justify="center" vertical><Card
|
||||||
@@ -75,11 +77,11 @@ export default function LoginPage() {
|
|||||||
{t`Submit`}
|
{t`Submit`}
|
||||||
</Button>
|
</Button>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item wrapperCol={{offset: 8, span: 16}}>
|
{configuration?.ssoLogin && <Form.Item wrapperCol={{offset: 8, span: 16}}>
|
||||||
<Button type="primary" htmlType="button" href="/login/oauth">
|
<Button type="primary" htmlType="button" href="/login/oauth">
|
||||||
{t`Log in with SSO`}
|
{t`Log in with SSO`}
|
||||||
</Button>
|
</Button>
|
||||||
</Form.Item>
|
</Form.Item>}
|
||||||
</Form>
|
</Form>
|
||||||
</Card>
|
</Card>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|||||||
@@ -71,6 +71,11 @@ export interface Watchlist {
|
|||||||
connector?: string
|
connector?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface InstanceConfig {
|
||||||
|
ssoLogin: boolean
|
||||||
|
limtedFeatures: boolean
|
||||||
|
}
|
||||||
|
|
||||||
export async function request<T = any, R = AxiosResponse<T>, D = any>(config: AxiosRequestConfig): Promise<R> {
|
export async function request<T = any, R = AxiosResponse<T>, D = any>(config: AxiosRequestConfig): Promise<R> {
|
||||||
const axiosConfig: AxiosRequestConfig = {
|
const axiosConfig: AxiosRequestConfig = {
|
||||||
...config,
|
...config,
|
||||||
@@ -84,6 +89,7 @@ export async function request<T = any, R = AxiosResponse<T>, D = any>(config: Ax
|
|||||||
return await axios.request<T, R, D>(axiosConfig)
|
return await axios.request<T, R, D>(axiosConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export * from './domain'
|
export * from './domain'
|
||||||
export * from './tld'
|
export * from './tld'
|
||||||
export * from './user'
|
export * from './user'
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import {request, User} from "./index";
|
import {InstanceConfig, request, User} from "./index";
|
||||||
|
|
||||||
|
|
||||||
export async function login(email: string, password: string): Promise<boolean> {
|
export async function login(email: string, password: string): Promise<boolean> {
|
||||||
@@ -16,3 +16,10 @@ export async function getUser(): Promise<User> {
|
|||||||
})
|
})
|
||||||
return response.data
|
return response.data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getConfiguration(): Promise<InstanceConfig> {
|
||||||
|
const response = await request<InstanceConfig>({
|
||||||
|
url: 'config'
|
||||||
|
})
|
||||||
|
return response.data
|
||||||
|
}
|
||||||
@@ -70,6 +70,7 @@ security:
|
|||||||
- { path: ^/api$, roles: PUBLIC_ACCESS }
|
- { path: ^/api$, roles: PUBLIC_ACCESS }
|
||||||
- { path: ^/api/docs, roles: PUBLIC_ACCESS }
|
- { path: ^/api/docs, roles: PUBLIC_ACCESS }
|
||||||
- { path: "^/api/watchlists/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/calendar$", roles: PUBLIC_ACCESS }
|
- { path: "^/api/watchlists/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/calendar$", roles: PUBLIC_ACCESS }
|
||||||
|
- { path: "^/api/config$", roles: PUBLIC_ACCESS }
|
||||||
- { path: ^/api, roles: IS_AUTHENTICATED_FULLY }
|
- { path: ^/api, roles: IS_AUTHENTICATED_FULLY }
|
||||||
|
|
||||||
when@test:
|
when@test:
|
||||||
|
|||||||
@@ -4,7 +4,9 @@
|
|||||||
# Put parameters here that don't need to change on each machine where the app is deployed
|
# Put parameters here that don't need to change on each machine where the app is deployed
|
||||||
# https://symfony.com/doc/current/best_practices.html#use-parameters-for-application-configuration
|
# https://symfony.com/doc/current/best_practices.html#use-parameters-for-application-configuration
|
||||||
parameters:
|
parameters:
|
||||||
mailer_sender_email: '%env(MAILER_SENDER_EMAIL)%'
|
mailer_sender_email: '%env(string:MAILER_SENDER_EMAIL)%'
|
||||||
|
oauth_enabled: '%env(bool:OAUTH_ENABLED)%'
|
||||||
|
limited_features: '%env(bool:LIMITED_FEATURES)%'
|
||||||
|
|
||||||
services:
|
services:
|
||||||
# default configuration for services in *this* file
|
# default configuration for services in *this* file
|
||||||
|
|||||||
20
src/Controller/InstanceController.php
Normal file
20
src/Controller/InstanceController.php
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Controller;
|
||||||
|
|
||||||
|
use App\Entity\Instance;
|
||||||
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
|
|
||||||
|
class InstanceController extends AbstractController
|
||||||
|
{
|
||||||
|
public function __invoke(): Instance
|
||||||
|
{
|
||||||
|
$instance = new Instance();
|
||||||
|
|
||||||
|
$instance
|
||||||
|
->setLimitedFeatures($this->getParameter('limited_features') ?? false)
|
||||||
|
->setOauthEnabled($this->getParameter('oauth_enabled'));
|
||||||
|
|
||||||
|
return $instance;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -24,11 +24,13 @@ use Symfony\Component\Uid\Uuid;
|
|||||||
name: 'get_all_mine',
|
name: 'get_all_mine',
|
||||||
),
|
),
|
||||||
new Get(
|
new Get(
|
||||||
normalizationContext: ['groups' => 'connector:list']
|
normalizationContext: ['groups' => 'connector:list'],
|
||||||
|
security: 'object.user == user'
|
||||||
),
|
),
|
||||||
new Post(
|
new Post(
|
||||||
routeName: 'connector_create', normalizationContext: ['groups' => ['connector:create', 'connector:list']],
|
routeName: 'connector_create',
|
||||||
denormalizationContext: ['groups' => 'connector:create'],
|
normalizationContext: ['groups' => ['connector:create', 'connector:list']], denormalizationContext: ['groups' => 'connector:create'],
|
||||||
|
security: 'object.user == user',
|
||||||
name: 'create'
|
name: 'create'
|
||||||
),
|
),
|
||||||
new Delete(),
|
new Delete(),
|
||||||
@@ -44,7 +46,7 @@ class Connector
|
|||||||
|
|
||||||
#[ORM\ManyToOne(inversedBy: 'connectors')]
|
#[ORM\ManyToOne(inversedBy: 'connectors')]
|
||||||
#[ORM\JoinColumn(nullable: false)]
|
#[ORM\JoinColumn(nullable: false)]
|
||||||
private ?User $user = null;
|
public ?User $user = null;
|
||||||
|
|
||||||
#[Groups(['connector:list', 'connector:create', 'watchlist:list'])]
|
#[Groups(['connector:list', 'connector:create', 'watchlist:list'])]
|
||||||
#[ORM\Column(enumType: ConnectorProvider::class)]
|
#[ORM\Column(enumType: ConnectorProvider::class)]
|
||||||
|
|||||||
48
src/Entity/Instance.php
Normal file
48
src/Entity/Instance.php
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Entity;
|
||||||
|
|
||||||
|
use ApiPlatform\Metadata\ApiResource;
|
||||||
|
use ApiPlatform\Metadata\Get;
|
||||||
|
use App\Controller\InstanceController;
|
||||||
|
|
||||||
|
#[ApiResource(
|
||||||
|
operations: [
|
||||||
|
new Get(
|
||||||
|
uriTemplate: '/config',
|
||||||
|
controller: InstanceController::class,
|
||||||
|
shortName: 'Configuration',
|
||||||
|
read: false,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
)]
|
||||||
|
class Instance
|
||||||
|
{
|
||||||
|
private ?bool $oauthEnabled = null;
|
||||||
|
|
||||||
|
private ?bool $limitedFeatures = null;
|
||||||
|
|
||||||
|
public function isSsoLogin(): ?bool
|
||||||
|
{
|
||||||
|
return $this->oauthEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setOauthEnabled(bool $oauthEnabled): static
|
||||||
|
{
|
||||||
|
$this->oauthEnabled = $oauthEnabled;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isLimitedFeatures(): ?bool
|
||||||
|
{
|
||||||
|
return $this->limitedFeatures;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setLimitedFeatures(bool $limitedFeatures): static
|
||||||
|
{
|
||||||
|
$this->limitedFeatures = $limitedFeatures;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -27,7 +27,8 @@ use Symfony\Component\Uid\Uuid;
|
|||||||
name: 'get_all_mine',
|
name: 'get_all_mine',
|
||||||
),
|
),
|
||||||
new Get(
|
new Get(
|
||||||
normalizationContext: ['groups' => 'watchlist:item']
|
normalizationContext: ['groups' => 'watchlist:item'],
|
||||||
|
security: 'object.user == user'
|
||||||
),
|
),
|
||||||
new Get(
|
new Get(
|
||||||
routeName: 'watchlist_calendar',
|
routeName: 'watchlist_calendar',
|
||||||
@@ -73,7 +74,7 @@ class WatchList
|
|||||||
|
|
||||||
#[ORM\ManyToOne(targetEntity: User::class, inversedBy: 'watchLists')]
|
#[ORM\ManyToOne(targetEntity: User::class, inversedBy: 'watchLists')]
|
||||||
#[ORM\JoinColumn(nullable: false)]
|
#[ORM\JoinColumn(nullable: false)]
|
||||||
private ?User $user = null;
|
public ?User $user = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var Collection<int, Domain>
|
* @var Collection<int, Domain>
|
||||||
|
|||||||
@@ -57,8 +57,8 @@ msgstr ""
|
|||||||
#: assets/components/tracking/ConnectorForm.tsx:110
|
#: assets/components/tracking/ConnectorForm.tsx:110
|
||||||
#: assets/components/tracking/ConnectorForm.tsx:119
|
#: assets/components/tracking/ConnectorForm.tsx:119
|
||||||
#: assets/components/tracking/WatchlistForm.tsx:102
|
#: assets/components/tracking/WatchlistForm.tsx:102
|
||||||
#: assets/pages/LoginPage.tsx:60
|
#: assets/pages/LoginPage.tsx:62
|
||||||
#: assets/pages/LoginPage.tsx:68
|
#: assets/pages/LoginPage.tsx:70
|
||||||
msgid "Required"
|
msgid "Required"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -319,7 +319,7 @@ msgid "Log out"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: assets/components/Sider.tsx:120
|
#: assets/components/Sider.tsx:120
|
||||||
#: assets/pages/LoginPage.tsx:38
|
#: assets/pages/LoginPage.tsx:40
|
||||||
msgid "Log in"
|
msgid "Log in"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -427,7 +427,7 @@ msgid ""
|
|||||||
"their country of origin."
|
"their country of origin."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: assets/pages/LoginPage.tsx:58
|
#: assets/pages/LoginPage.tsx:60
|
||||||
#: assets/pages/watchdog/UserPage.tsx:18
|
#: assets/pages/watchdog/UserPage.tsx:18
|
||||||
msgid "Username"
|
msgid "Username"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -456,19 +456,19 @@ msgstr ""
|
|||||||
msgid "Sorry, the page you visited does not exist."
|
msgid "Sorry, the page you visited does not exist."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: assets/pages/LoginPage.tsx:43
|
#: assets/pages/LoginPage.tsx:45
|
||||||
msgid "Error"
|
msgid "Error"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: assets/pages/LoginPage.tsx:66
|
#: assets/pages/LoginPage.tsx:68
|
||||||
msgid "Password"
|
msgid "Password"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: assets/pages/LoginPage.tsx:75
|
#: assets/pages/LoginPage.tsx:77
|
||||||
msgid "Submit"
|
msgid "Submit"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: assets/pages/LoginPage.tsx:80
|
#: assets/pages/LoginPage.tsx:82
|
||||||
msgid "Log in with SSO"
|
msgid "Log in with SSO"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user