<commit_before>package com.cgi.eoss.ftep.security;

import com.cgi.eoss.ftep.model.FtepEntityWithOwner;
import com.cgi.eoss.ftep.model.Group;
import com.cgi.eoss.ftep.model.Role;
import com.cgi.eoss.ftep.model.User;
import com.cgi.eoss.ftep.persistence.service.PublishingRequestDataService;
import com.cgi.eoss.ftep.persistence.service.UserDataService;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.acls.AclPermissionEvaluator;
import org.springframework.security.acls.domain.BasePermission;
import org.springframework.security.acls.domain.GrantedAuthoritySid;
import org.springframework.security.acls.domain.ObjectIdentityImpl;
import org.springframework.security.acls.domain.PrincipalSid;
import org.springframework.security.acls.model.Acl;
import org.springframework.security.acls.model.MutableAcl;
import org.springframework.security.acls.model.MutableAclService;
import org.springframework.security.acls.model.NotFoundException;
import org.springframework.security.acls.model.ObjectIdentity;
import org.springframework.security.acls.model.Sid;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.IntStream;

import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;
import static java.util.stream.Collectors.toSet;

/**
 * <p>Provides common utility-style methods for interacting with the F-TEP security context.</p>
 */
@Component
@Log4j2
@Transactional(readOnly = true)
public class FtepSecurityService {
    public static final Authentication PUBLIC_AUTHENTICATION = new PreAuthenticatedAuthenticationToken("PUBLIC", "N/A", ImmutableList.of(FtepPermission.PUBLIC));

    private static final Predicate<GrantedAuthority> ADMIN_PREDICATE = a -> Role.ADMIN.getAuthority().equals(a.getAuthority());
    private static final Predicate<GrantedAuthority> SUPERUSER_PREDICATE = ADMIN_PREDICATE.or(a -> Role.CONTENT_AUTHORITY.getAuthority().equals(a.getAuthority()));

    private final MutableAclService aclService;
    private final AclPermissionEvaluator aclPermissionEvaluator;
    private final UserDataService userDataService;
    private final PublishingRequestDataService publishingRequestDataService;

    @Autowired
    public FtepSecurityService(MutableAclService aclService, AclPermissionEvaluator aclPermissionEvaluator, UserDataService userDataService, PublishingRequestDataService publishingRequestDataService) {
        this.aclService = aclService;
        this.aclPermissionEvaluator = aclPermissionEvaluator;
        this.userDataService = userDataService;
        this.publishingRequestDataService = publishingRequestDataService;
    }

    public void updateOwnerWithCurrentUser(FtepEntityWithOwner entity) {
        entity.setOwner(getCurrentUser());
    }

    public User getCurrentUser() {
        String username = getCurrentAuthentication().getName();
        return userDataService.getByName(username);
    }

    public Collection<? extends GrantedAuthority> getCurrentAuthorities() {
        return getCurrentAuthentication().getAuthorities();
    }

    public Set<Group> getCurrentGroups() {
        return getCurrentUser().getGroups();
    }

    public User refreshPersistentUser(User user) {
        return userDataService.refresh(user);
    }

    /**
     * <p>Create an access control entry granting all users (the PUBLIC authority) READ access to the given object.</p>
     *
     * @param objectClass The class of the entity being published.
     * @param identifier  The identifier of the entity being published.
     */
    public void publish(Class<?> objectClass, Long identifier) {
        LOG.info("Publishing entity: {} (id: {})", objectClass, identifier);

        publish(new ObjectIdentityImpl(objectClass, identifier));
    }

    /**
     * <p>Create an access control entry granting all users (the PUBLIC authority) READ access to the given object.</p>
     *
     * @param objectIdentity The identifier of the entity being published.
     */
    public void publish(ObjectIdentity objectIdentity) {
        MutableAcl acl = getAcl(objectIdentity);

        Sid publicSid = new GrantedAuthoritySid(FtepPermission.PUBLIC);

        FtepPermission.READ.getAclPermissions()
                .forEach(p -> acl.insertAce(acl.getEntries().size(), p, publicSid, true));

        saveAcl(acl);
    }

    public void unpublish(Class<?> objectClass, Long identifier) {
        if (!isPublic(new ObjectIdentityImpl(objectClass, identifier))) {
            LOG.warn("Attempted to unpublish non-public object: {} {}", objectClass, identifier);
            return;
        }

        LOG.info("Unpublishing entity: {} (id: {})", objectClass, identifier);
        MutableAcl acl = getAcl(new ObjectIdentityImpl(objectClass, identifier));

        Sid publicSid = new GrantedAuthoritySid(FtepPermission.PUBLIC);
<commit_msg>Fix security service transactionality<commit_after>package com.cgi.eoss.ftep.security;

import com.cgi.eoss.ftep.model.FtepEntityWithOwner;
import com.cgi.eoss.ftep.model.Group;
import com.cgi.eoss.ftep.model.Role;
import com.cgi.eoss.ftep.model.User;
import com.cgi.eoss.ftep.persistence.service.PublishingRequestDataService;
import com.cgi.eoss.ftep.persistence.service.UserDataService;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.acls.AclPermissionEvaluator;
import org.springframework.security.acls.domain.BasePermission;
import org.springframework.security.acls.domain.GrantedAuthoritySid;
import org.springframework.security.acls.domain.ObjectIdentityImpl;
import org.springframework.security.acls.domain.PrincipalSid;
import org.springframework.security.acls.model.Acl;
import org.springframework.security.acls.model.MutableAcl;
import org.springframework.security.acls.model.MutableAclService;
import org.springframework.security.acls.model.NotFoundException;
import org.springframework.security.acls.model.ObjectIdentity;
import org.springframework.security.acls.model.Sid;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.IntStream;

import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;
import static java.util.stream.Collectors.toSet;

/**
 * <p>Provides common utility-style methods for interacting with the F-TEP security context.</p>
 */
@Component
@Log4j2
@Transactional(readOnly = true)
public class FtepSecurityService {
    public static final Authentication PUBLIC_AUTHENTICATION = new PreAuthenticatedAuthenticationToken("PUBLIC", "N/A", ImmutableList.of(FtepPermission.PUBLIC));

    private static final Predicate<GrantedAuthority> ADMIN_PREDICATE = a -> Role.ADMIN.getAuthority().equals(a.getAuthority());
    private static final Predicate<GrantedAuthority> SUPERUSER_PREDICATE = ADMIN_PREDICATE.or(a -> Role.CONTENT_AUTHORITY.getAuthority().equals(a.getAuthority()));

    private final MutableAclService aclService;
    private final AclPermissionEvaluator aclPermissionEvaluator;
    private final UserDataService userDataService;
    private final PublishingRequestDataService publishingRequestDataService;

    @Autowired
    public FtepSecurityService(MutableAclService aclService, AclPermissionEvaluator aclPermissionEvaluator, UserDataService userDataService, PublishingRequestDataService publishingRequestDataService) {
        this.aclService = aclService;
        this.aclPermissionEvaluator = aclPermissionEvaluator;
        this.userDataService = userDataService;
        this.publishingRequestDataService = publishingRequestDataService;
    }

    public void updateOwnerWithCurrentUser(FtepEntityWithOwner entity) {
        entity.setOwner(getCurrentUser());
    }

    public User getCurrentUser() {
        String username = getCurrentAuthentication().getName();
        return userDataService.getByName(username);
    }

    public Collection<? extends GrantedAuthority> getCurrentAuthorities() {
        return getCurrentAuthentication().getAuthorities();
    }

    public Set<Group> getCurrentGroups() {
        return getCurrentUser().getGroups();
    }

    public User refreshPersistentUser(User user) {
        return userDataService.refresh(user);
    }

    /**
     * <p>Create an access control entry granting all users (the PUBLIC authority) READ access to the given object.</p>
     *
     * @param objectClass The class of the entity being published.
     * @param identifier  The identifier of the entity being published.
     */
    @Transactional
    public void publish(Class<?> objectClass, Long identifier) {
        LOG.info("Publishing entity: {} (id: {})", objectClass, identifier);

        publish(new ObjectIdentityImpl(objectClass, identifier));
    }

    /**
     * <p>Create an access control entry granting all users (the PUBLIC authority) READ access to the given object.</p>
     *
     * @param objectIdentity The identifier of the entity being published.
     */
    @Transactional
    public void publish(ObjectIdentity objectIdentity) {
        MutableAcl acl = getAcl(objectIdentity);

        Sid publicSid = new GrantedAuthoritySid(FtepPermission.PUBLIC);

        FtepPermission.READ.getAclPermissions()
                .forEach(p -> acl.insertAce(acl.getEntries().size(), p, publicSid, true));

        saveAcl(acl);
    }

    @Transactional
    public void unpublish(Class<?> objectClass, Long identifier) {
        if (!isPublic(new ObjectIdentityImpl(objectClass, identifier))) {
            LOG.warn("Attempted to unpublish non-public object: {} {}", objectClass, identifier);
            return;
        }

        LOG.info("Unpublishing entity: {} (id: {})", objectClass, identifier);
        MutableAcl acl = getAcl(new ObjectIdentityImpl(objectClass, identifier));

        Sid publicSid = new GrantedAuthoritySid(FtepPermission.PUBLIC);

{'fraction_non_alphanumeric': 0.09396269778131354, 'fraction_numerical': 0.0008839388314328649, 'mean_word_length': 4.7402333840690005, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 33, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2280231', 'n_tokens_mistral': 3168, 'n_tokens_neox': 3093, 'n_words': 634}