Added permissions to control access to API and manage API tokens

This commit is contained in:
Jan Böhmer 2023-08-26 22:57:50 +02:00
parent be14fe548c
commit 8fe3f4cf5c
7 changed files with 60 additions and 26 deletions

View file

@ -69,3 +69,5 @@ security:
# We get into trouble with the U2F authentication, if the calls to the trees trigger an 2FA login
# This settings should not do much harm, because a read only access to show available data structures is not really critical
- { path: "^/\\w{2}/tree", role: PUBLIC_ACCESS }
# Restrict access to API to users, which has the API access permission
- { path: "^/api", allow_if: 'is_granted("@api.access_api") and is_authenticated()' }

View file

@ -254,6 +254,7 @@ perms: # Here comes a list with all Permission names (they have a perm_[name] co
show_updates:
label: "perm.system.show_available_updates"
attachments:
label: "perm.part.attachments"
operations:
@ -304,4 +305,11 @@ perms: # Here comes a list with all Permission names (they have a perm_[name] co
label: "perm.revert_elements"
alsoSet: ['read_profiles', 'edit_profiles', 'create_profiles', 'delete_profiles']
api:
label: "perm.api"
operations:
access_api:
label: "perm.api.access_api"
manage_tokens:
label: "perm.api.manage_tokens"
alsoSet: ['access_api']

View file

@ -406,6 +406,8 @@ class UserSettingsController extends AbstractController
#[Route('/api_token/create', name: 'user_api_token_create')]
public function addApiToken(Request $request, EntityManagerInterface $entityManager): Response
{
$this->denyAccessUnlessGranted('@api.manage_tokens');
$token = new ApiToken();
$token->setUser($this->getUser());

View file

@ -102,7 +102,7 @@ class User extends AttachmentContainingDBElement implements UserInterface, HasPe
final public const ID_ANONYMOUS = 1;
#[Groups(['user:read'])]
protected ?int $id;
protected ?int $id = null;
#[Groups(['user:read'])]
protected ?\DateTimeInterface $lastModified = null;

View file

@ -55,7 +55,9 @@
</table>
{% endif %}
<a href="{{ path('user_api_token_create') }}" class="btn btn-success" ><i class="fas fa-plus-square fa-fw"></i> {% trans %}api_token.create_new{% endtrans %}</a>
<a href="{{ path('user_api_token_create') }}" class="btn btn-success" {% if not is_granted('@api.manage_tokens') %}disabled="disabled"{% endif %}>
<i class="fas fa-plus-square fa-fw"></i> {% trans %}api_token.create_new{% endtrans %}
</a>
</div>
</div>

View file

@ -77,5 +77,7 @@
</div>
</div>
{% if is_granted("@api.access_api") %}
{% include "users/_api_tokens.html.twig" %}
{% endif %}
{% endblock %}

View file

@ -731,10 +731,10 @@
</notes>
<segment>
<source>user.edit.tfa.disable_tfa_message</source>
<target>This will disable &lt;b&gt;all active two-factor authentication methods of the user&lt;/b&gt; and delete the &lt;b&gt;backup codes&lt;/b&gt;!
&lt;br&gt;
The user will have to set up all two-factor authentication methods again and print new backup codes! &lt;br&gt;&lt;br&gt;
&lt;b&gt;Only do this if you are absolutely sure about the identity of the user (seeking help), otherwise the account could be compromised by an attacker!&lt;/b&gt;</target>
<target><![CDATA[This will disable <b>all active two-factor authentication methods of the user</b> and delete the <b>backup codes</b>!
<br>
The user will have to set up all two-factor authentication methods again and print new backup codes! <br><br>
<b>Only do this if you are absolutely sure about the identity of the user (seeking help), otherwise the account could be compromised by an attacker!</b>]]></target>
</segment>
</unit>
<unit id="02HvwiS" name="user.edit.tfa.disable_tfa.btn">
@ -11326,67 +11326,67 @@ Element 3</target>
</segment>
</unit>
<unit id="DGczoY6" name="tfa_u2f.add_key.registration_error">
<segment state="translated">
<segment>
<source>tfa_u2f.add_key.registration_error</source>
<target>An error occurred during the registration of the security key. Try again or use another security key!</target>
</segment>
</unit>
<unit id="ie0Ca0l" name="log.target_type.none">
<segment state="translated">
<segment>
<source>log.target_type.none</source>
<target>None</target>
</segment>
</unit>
<unit id="R2nX4ip" name="ui.darkmode.light">
<segment state="translated">
<segment>
<source>ui.darkmode.light</source>
<target>Light</target>
</segment>
</unit>
<unit id="3NHpuW3" name="ui.darkmode.dark">
<segment state="translated">
<segment>
<source>ui.darkmode.dark</source>
<target>Dark</target>
</segment>
</unit>
<unit id="4TGOK5_" name="ui.darkmode.auto">
<segment state="translated">
<segment>
<source>ui.darkmode.auto</source>
<target>Auto (decide based on system settings)</target>
</segment>
</unit>
<unit id="9N0N8aL" name="label_generator.no_lines_given">
<segment state="translated">
<segment>
<source>label_generator.no_lines_given</source>
<target>No text content given! The labels will remain empty.</target>
</segment>
</unit>
<unit id="RdFvZsb" name="user.password_strength.very_weak">
<segment state="translated">
<segment>
<source>user.password_strength.very_weak</source>
<target>Very weak</target>
</segment>
</unit>
<unit id="IBjmblZ" name="user.password_strength.weak">
<segment state="translated">
<segment>
<source>user.password_strength.weak</source>
<target>Weak</target>
</segment>
</unit>
<unit id="qSm_ID0" name="user.password_strength.medium">
<segment state="translated">
<segment>
<source>user.password_strength.medium</source>
<target>Medium</target>
</segment>
</unit>
<unit id="aWAaADS" name="user.password_strength.strong">
<segment state="translated">
<segment>
<source>user.password_strength.strong</source>
<target>Strong</target>
</segment>
</unit>
<unit id="Wa9CStW" name="user.password_strength.very_strong">
<segment state="translated">
<segment>
<source>user.password_strength.very_strong</source>
<target>Very strong</target>
</segment>
@ -11580,25 +11580,25 @@ Please note, that you can not impersonate a disabled user. If you try you will g
</segment>
</unit>
<unit id="21tIbM2" name="update_manager.new_version_available.title">
<segment state="translated">
<segment>
<source>update_manager.new_version_available.title</source>
<target>New version available</target>
</segment>
</unit>
<unit id=".c.eoDV" name="update_manager.new_version_available.text">
<segment state="translated">
<segment>
<source>update_manager.new_version_available.text</source>
<target>A new version of Part-DB is available. Check it out here</target>
</segment>
</unit>
<unit id="KOFGqJw" name="update_manager.new_version_available.only_administrators_can_see">
<segment state="translated">
<segment>
<source>update_manager.new_version_available.only_administrators_can_see</source>
<target>Only administrators can see this message.</target>
</segment>
</unit>
<unit id="IFkvJpC" name="perm.system.show_available_updates">
<segment state="translated">
<segment>
<source>perm.system.show_available_updates</source>
<target>Show available Part-DB updates</target>
</segment>
@ -11730,22 +11730,40 @@ Please note, that you can not impersonate a disabled user. If you try you will g
</segment>
</unit>
<unit id="VVpmfIj" name="project.build.dont_check_quantity">
<segment state="translated">
<segment>
<source>project.build.dont_check_quantity</source>
<target>Do not check quantities</target>
</segment>
</unit>
<unit id="AzYSIiX" name="project.build.dont_check_quantity.help">
<segment state="translated">
<segment>
<source>project.build.dont_check_quantity.help</source>
<target>If this option is selected, the given withdraw quantities are used as given, no matter if more or less parts are actually required to build this project.</target>
</segment>
</unit>
<unit id="tfOeMsC" name="part_list.action.invert_selection">
<segment state="translated">
<segment>
<source>part_list.action.invert_selection</source>
<target>Invert selection</target>
</segment>
</unit>
<unit id="vvmdRvD" name="perm.api">
<segment>
<source>perm.api</source>
<target>API</target>
</segment>
</unit>
<unit id="VrWd7Fb" name="perm.api.access_api">
<segment>
<source>perm.api.access_api</source>
<target>Access API</target>
</segment>
</unit>
<unit id="hLOM1pt" name="perm.api.manage_tokens">
<segment>
<source>perm.api.manage_tokens</source>
<target>Manage API tokens</target>
</segment>
</unit>
</file>
</xliff>