CCM NG: Revised Im/Export system for entities in org.libreccm-security

git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@5706 8810af33-2d31-482b-a856-94f89814c4df

Former-commit-id: 2d6e92ea43
pull/2/head
jensp 2018-10-03 08:08:35 +00:00
parent 07be087a16
commit 732c9d7881
64 changed files with 728 additions and 535 deletions

View File

@ -0,0 +1,68 @@
/*
* Copyright (C) 2018 LibreCCM Foundation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package org.libreccm.imexport;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
/**
* Base class for importers/exporters. Implementations must be annotated with
* {@link Procsses} to register the implementation in the Import/Export service.
*
* Implementations must also be CDI beans. It is recommended that the beans are
* {@link RequestScoped}.
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
* @param <T> The type of the entity which is processed by the implementation.
*/
public abstract class AbstractEntityImExporter<T extends Exportable> {
private final ObjectMapper objectMapper = new ObjectMapper();
protected abstract Class<T> getEntityClass();
public T importEntity(final String data) throws ImportExpection {
try {
return objectMapper.readValue(data, getEntityClass());
} catch (IOException ex) {
throw new ImportExpection(ex);
}
}
public String exportEntity(final Exportable entity) throws ExportException {
try {
return objectMapper.writeValueAsString(entity);
} catch (JsonProcessingException ex) {
throw new ExportException(String.format(
"Failed to export entity \"%s\" of type \"%s\".",
entity.getUuid(),
getEntityClass().getName()),
ex);
}
}
protected abstract void saveImportedEntity(T entity);
}

View File

@ -35,7 +35,7 @@ import java.util.stream.Collectors;
* method. With the returned list of nodes call the * method. With the returned list of nodes call the
* {@link #orderImExporters(java.util.List)} method. The list returned by * {@link #orderImExporters(java.util.List)} method. The list returned by
* {@link #orderImExporters(java.util.List)} contains all * {@link #orderImExporters(java.util.List)} contains all
* {@link EntityImExporter} in the order. * {@link AbstractEntityImExporter}s in the order.
* *
* This class is <strong>not</strong> not part of the public API. * This class is <strong>not</strong> not part of the public API.
* *
@ -50,9 +50,9 @@ final class EntityImExporterTreeManager {
.getLogger(EntityImExporterTreeManager.class); .getLogger(EntityImExporterTreeManager.class);
/** /**
* Initialises the tree with the provided list of {@link EntityImExporter}s. * Initialises the tree with the provided list of {@link AbstractEntityImExporter}s.
* *
* @param imExporters The available {@link EntityImExporter}s. * @param imExporters The available {@link AbstractEntityImExporter}s.
* *
* @return An ordered list of the tree nodes. * @return An ordered list of the tree nodes.
* *
@ -62,7 +62,7 @@ final class EntityImExporterTreeManager {
* cycle is detected in the dependency tree. * cycle is detected in the dependency tree.
*/ */
public List<EntityImExporterTreeNode> generateTree( public List<EntityImExporterTreeNode> generateTree(
final List<EntityImExporter<?>> imExporters) final List<AbstractEntityImExporter<?>> imExporters)
throws DependencyException { throws DependencyException {
LOGGER.info("Starting to generate dependency tree..."); LOGGER.info("Starting to generate dependency tree...");
@ -81,7 +81,7 @@ final class EntityImExporterTreeManager {
node -> node)); node -> node));
//Add the dependency relations to the nodes //Add the dependency relations to the nodes
for (final EntityImExporter<?> imExporter : imExporters) { for (final AbstractEntityImExporter<?> imExporter : imExporters) {
addDependencyRelations(imExporter, nodes); addDependencyRelations(imExporter, nodes);
} }
@ -184,7 +184,7 @@ final class EntityImExporterTreeManager {
/** /**
* Helper method for adding the dependency relations for an * Helper method for adding the dependency relations for an
* {@link EntityImExporter} to the nodes. * {@link AbstractEntityImExporter} to the nodes.
* *
* @param imExporter The current {@link EntityImExporter}. * @param imExporter The current {@link EntityImExporter}.
* @param nodes The map of nodes. * @param nodes The map of nodes.
@ -192,7 +192,7 @@ final class EntityImExporterTreeManager {
* @throws DependencyException If something goes wrong. * @throws DependencyException If something goes wrong.
*/ */
private void addDependencyRelations( private void addDependencyRelations(
final EntityImExporter<?> imExporter, final AbstractEntityImExporter<?> imExporter,
final Map<String, EntityImExporterTreeNode> nodes) final Map<String, EntityImExporterTreeNode> nodes)
throws DependencyException { throws DependencyException {

View File

@ -29,7 +29,7 @@ import java.util.Objects;
*/ */
final class EntityImExporterTreeNode { final class EntityImExporterTreeNode {
private EntityImExporter<?> entityImExporter; private AbstractEntityImExporter<?> entityImExporter;
private List<EntityImExporterTreeNode> dependentImExporters; private List<EntityImExporterTreeNode> dependentImExporters;
@ -44,18 +44,19 @@ final class EntityImExporterTreeNode {
} }
public EntityImExporterTreeNode( public EntityImExporterTreeNode(
final EntityImExporter<?> entityImExporter) { final AbstractEntityImExporter<?> entityImExporter) {
this(); this();
this.entityImExporter = entityImExporter; this.entityImExporter = entityImExporter;
} }
public EntityImExporter<?> getEntityImExporter() { public AbstractEntityImExporter<?> getEntityImExporter() {
return entityImExporter; return entityImExporter;
} }
void setEntityImExporter(final EntityImExporter<?> entityImExporter) { void setEntityImExporter(
final AbstractEntityImExporter<?> entityImExporter) {
this.entityImExporter = entityImExporter; this.entityImExporter = entityImExporter;
} }

View File

@ -0,0 +1,67 @@
/*
* Copyright (C) 2018 LibreCCM Foundation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package org.libreccm.imexport;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
public class ExportException extends Exception {
private static final long serialVersionUID = 1L;
/**
* Creates a new instance of <code>ExportException</code> without detail message.
*/
public ExportException() {
super();
}
/**
* Constructs an instance of <code>ExportException</code> with the specified detail message.
*
* @param msg The detail message.
*/
public ExportException(final String msg) {
super(msg);
}
/**
* Constructs an instance of <code>ExportException</code> which wraps the
* specified exception.
*
* @param exception The exception to wrap.
*/
public ExportException(final Exception exception) {
super(exception);
}
/**
* Constructs an instance of <code>ExportException</code> with the specified message which also wraps the
* specified exception.
*
* @param msg The detail message.
* @param exception The exception to wrap.
*/
public ExportException(final String msg, final Exception exception) {
super(msg, exception);
}
}

View File

@ -0,0 +1,67 @@
/*
* Copyright (C) 2018 LibreCCM Foundation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package org.libreccm.imexport;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
public class ImportExpection extends Exception {
private static final long serialVersionUID = 1L;
/**
* Creates a new instance of <code>ImportExpection</code> without detail message.
*/
public ImportExpection() {
super();
}
/**
* Constructs an instance of <code>ImportExpection</code> with the specified detail message.
*
* @param msg The detail message.
*/
public ImportExpection(final String msg) {
super(msg);
}
/**
* Constructs an instance of <code>ImportExpection</code> which wraps the
* specified exception.
*
* @param exception The exception to wrap.
*/
public ImportExpection(final Exception exception) {
super(exception);
}
/**
* Constructs an instance of <code>ImportExpection</code> with the specified message which also wraps the
* specified exception.
*
* @param msg The detail message.
* @param exception The exception to wrap.
*/
public ImportExpection(final String msg, final Exception exception) {
super(msg, exception);
}
}

View File

@ -26,11 +26,15 @@ import org.libreccm.files.FileAlreadyExistsException;
import org.libreccm.files.FileDoesNotExistException; import org.libreccm.files.FileDoesNotExistException;
import org.libreccm.files.InsufficientPermissionsException; import org.libreccm.files.InsufficientPermissionsException;
import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.ZoneId; import java.time.ZoneId;
import java.util.ArrayList; import java.util.ArrayList;
@ -39,6 +43,8 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.enterprise.context.RequestScoped; import javax.enterprise.context.RequestScoped;
@ -68,7 +74,7 @@ public class ImportExport {
@Inject @Inject
@Any @Any
private Instance<EntityImExporter<?>> imExporters; private Instance<AbstractEntityImExporter<?>> imExporters;
/** /**
* Exports the provided entities. The export will be written to a to the * Exports the provided entities. The export will be written to a to the
@ -162,10 +168,10 @@ public class ImportExport {
throw new UnexpectedErrorException(ex); throw new UnexpectedErrorException(ex);
} }
final Instance<EntityImExporter<?>> instance = imExporters final Instance<AbstractEntityImExporter<?>> instance = imExporters
.select(new ProcessesLiteral(clazz)); .select(new ProcessesLiteral(clazz));
final EntityImExporter<?> imExporter; final AbstractEntityImExporter<?> imExporter;
if (instance.isUnsatisfied()) { if (instance.isUnsatisfied()) {
throw new UnexpectedErrorException(String.format( throw new UnexpectedErrorException(String.format(
"No EntityImExporter for entity type \"%s\" available.", "No EntityImExporter for entity type \"%s\" available.",
@ -195,10 +201,23 @@ public class ImportExport {
throw new UnexpectedErrorException(ex); throw new UnexpectedErrorException(ex);
} }
final JsonObject exportedEntity = imExporter.exportEntity(entity); final String exportedEntity;
try (JsonWriter writer = Json.createWriter(outputStream)) { try {
writer.writeObject(exportedEntity); exportedEntity = imExporter.exportEntity(entity);
} catch (ExportException ex) {
throw new UnexpectedErrorException(ex);
} }
try (final OutputStreamWriter writer = new OutputStreamWriter(
outputStream, StandardCharsets.UTF_8)) {
writer.write(exportedEntity);
} catch (IOException ex) {
throw new UnexpectedErrorException(ex);
}
// try (JsonWriter writer = Json.createWriter(outputStream)) {
// writer.writeObject(exportedEntity);
// }
} }
return filesArrayBuilder; return filesArrayBuilder;
@ -235,7 +254,8 @@ public class ImportExport {
throw new UnexpectedErrorException(ex); throw new UnexpectedErrorException(ex);
} }
final List<EntityImExporter<?>> imExportersList = new ArrayList<>(); final List<AbstractEntityImExporter<?>> imExportersList
= new ArrayList<>();
imExporters.forEach(imExporter -> imExportersList.add(imExporter)); imExporters.forEach(imExporter -> imExportersList.add(imExporter));
try { try {
@ -270,7 +290,8 @@ public class ImportExport {
private boolean filterImporters(final ImportManifest manifest, private boolean filterImporters(final ImportManifest manifest,
final EntityImExporterTreeNode node) { final EntityImExporterTreeNode node) {
final EntityImExporter<?> imExporter = node.getEntityImExporter(); final AbstractEntityImExporter<?> imExporter = node
.getEntityImExporter();
final String type = imExporter final String type = imExporter
.getClass() .getClass()
.getAnnotation(Processes.class).value().getName(); .getAnnotation(Processes.class).value().getName();
@ -280,7 +301,7 @@ public class ImportExport {
private void importEntitiesOfType( private void importEntitiesOfType(
final String importName, final String importName,
final EntityImExporter<?> entityImExporter) { final AbstractEntityImExporter<?> entityImExporter) {
final String type = entityImExporter final String type = entityImExporter
.getClass() .getClass()
@ -313,7 +334,7 @@ public class ImportExport {
private void importEntity(final String importName, private void importEntity(final String importName,
final String type, final String type,
final String fileName, final String fileName,
final EntityImExporter<?> imExporter) { final AbstractEntityImExporter<?> imExporter) {
final String filePath = String.format("imports/%s/%s/%s", final String filePath = String.format("imports/%s/%s/%s",
importName, importName,
@ -322,15 +343,20 @@ public class ImportExport {
try (final InputStream inputStream try (final InputStream inputStream
= ccmFiles.createInputStream(filePath)) { = ccmFiles.createInputStream(filePath)) {
final JsonReader reader = Json.createReader(inputStream); final String data = new BufferedReader(
final JsonObject data = reader.readObject(); new InputStreamReader(inputStream, StandardCharsets.UTF_8))
.lines()
.collect(Collectors.joining("\n"));
// final JsonReader reader = Json.createReader(inputStream);
// final JsonObject data = reader.readObject();
imExporter.importEntity(data); imExporter.importEntity(data);
} catch (IOException } catch (IOException
| FileDoesNotExistException | FileDoesNotExistException
| FileAccessException | FileAccessException
| InsufficientPermissionsException ex) { | InsufficientPermissionsException
| ImportExpection ex) {
throw new UnexpectedErrorException(ex); throw new UnexpectedErrorException(ex);
} }

View File

@ -21,7 +21,6 @@ package org.libreccm.security;
import com.fasterxml.jackson.annotation.JsonIdentityInfo; import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.ObjectIdGenerators; import com.fasterxml.jackson.annotation.ObjectIdGenerators;
import org.libreccm.portation.Portable;
import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlElementWrapper;
@ -35,6 +34,8 @@ import java.util.Set;
import static org.libreccm.core.CoreConstants.CORE_XML_NS; import static org.libreccm.core.CoreConstants.CORE_XML_NS;
import static org.libreccm.core.CoreConstants.DB_SCHEMA; import static org.libreccm.core.CoreConstants.DB_SCHEMA;
import org.libreccm.imexport.Exportable;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.FetchType; import javax.persistence.FetchType;
import javax.persistence.NamedAttributeNode; import javax.persistence.NamedAttributeNode;
@ -58,6 +59,10 @@ import javax.persistence.Table;
@Entity @Entity
@Table(name = "GROUPS", schema = DB_SCHEMA) @Table(name = "GROUPS", schema = DB_SCHEMA)
@NamedQueries({ @NamedQueries({
@NamedQuery(
name = "Group.findByUuid",
query = "SELECT g FROM Group g WHERE g.uuid = :uuid"
),
@NamedQuery( @NamedQuery(
name = "Group.findByName", name = "Group.findByName",
query = "SELECT g FROM Group g WHERE g.name = :name " query = "SELECT g FROM Group g WHERE g.name = :name "
@ -105,8 +110,8 @@ import javax.persistence.Table;
@XmlRootElement(name = "user-group", namespace = CORE_XML_NS) @XmlRootElement(name = "user-group", namespace = CORE_XML_NS)
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class,
resolver = GroupIdResolver.class, resolver = GroupIdResolver.class,
property = "name") property = "uuid")
public class Group extends Party implements Serializable, Portable { public class Group extends Party implements Serializable, Exportable {
private static final long serialVersionUID = -4800759206452780739L; private static final long serialVersionUID = -4800759206452780739L;

View File

@ -26,7 +26,7 @@ import javax.enterprise.context.RequestScoped;
import java.io.Serializable; import java.io.Serializable;
/** /**
* @author <a href="mailto:tosmers@uni-bremen.de>Tobias Osmers</a> * @author <a href="mailto:tosmers@uni-bremen.de">Tobias Osmers</a>
* @version created on 3/23/17 * @version created on 3/23/17
*/ */
@RequestScoped @RequestScoped
@ -43,14 +43,15 @@ public class GroupIdResolver implements Serializable, ObjectIdResolver {
@Override @Override
public Object resolveId(final ObjectIdGenerator.IdKey id) { public Object resolveId(final ObjectIdGenerator.IdKey id) {
final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final GroupRepository groupRepo = cdiUtil final GroupRepository groupRepo = cdiUtil
.findBean(GroupRepository.class); .findBean(GroupRepository.class);
return groupRepo return groupRepo
.findByName(id.key.toString()) .findByUuid(id.key.toString())
.orElseThrow(() -> new IllegalArgumentException(String .orElseThrow(() -> new IllegalArgumentException(String
.format("No Group with name %s in the database.", .format("No Group with uuid %s in the database.",
id.key.toString()))); id.key.toString())));
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2015 LibreCCM Foundation. * Copyright (C) 2018 LibreCCM Foundation.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@ -18,35 +18,34 @@
*/ */
package org.libreccm.security; package org.libreccm.security;
import org.libreccm.portation.AbstractMarshaller; import org.libreccm.imexport.AbstractEntityImExporter;
import org.libreccm.portation.Marshals; import org.libreccm.imexport.Processes;
import javax.enterprise.context.RequestScoped; import javax.enterprise.context.RequestScoped;
import javax.inject.Inject; import javax.inject.Inject;
import javax.transaction.Transactional; import javax.transaction.Transactional;
/** /**
* @author <a href="mailto:tosmers@uni-bremen.de>Tobias Osmers</a> *
* @version created on 11/7/16 * @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/ */
@RequestScoped @RequestScoped
@Marshals(Group.class) @Processes(Group.class)
public class GroupMarshaller extends AbstractMarshaller<Group> { public class GroupImExporter extends AbstractEntityImExporter<Group>{
private static final long serialVersionUID = 5004457104585052013L;
@Inject @Inject
private GroupRepository groupRepository; private GroupRepository groupRepository;
@Override @Override
protected Class<Group> getObjectClass() { protected Class<Group> getEntityClass() {
return Group.class; return Group.class;
} }
@Override @Override
@Transactional(Transactional.TxType.REQUIRED) @Transactional(Transactional.TxType.REQUIRED)
protected void insertIntoDb(Group portableObject) { protected void saveImportedEntity(final Group entity) {
portableObject.setPartyId(portableObject.getPartyId() * -1);
groupRepository.save(portableObject); groupRepository.save(entity);
} }
} }

View File

@ -26,8 +26,10 @@ import javax.persistence.EntityManager;
import javax.persistence.NoResultException; import javax.persistence.NoResultException;
import javax.persistence.TypedQuery; import javax.persistence.TypedQuery;
import javax.transaction.Transactional; import javax.transaction.Transactional;
import java.io.Serializable; import java.io.Serializable;
import java.util.List; import java.util.List;
import java.util.UUID;
/** /**
* Manager class providing methods for adding and removing members to and from * Manager class providing methods for adding and removing members to and from
@ -74,6 +76,7 @@ public class GroupManager implements Serializable {
} }
final GroupMembership membership = new GroupMembership(); final GroupMembership membership = new GroupMembership();
membership.setUuid(UUID.randomUUID().toString());
membership.setGroup(group); membership.setGroup(group);
membership.setMember(user); membership.setMember(user);

View File

@ -20,34 +20,50 @@ package org.libreccm.security;
import com.fasterxml.jackson.annotation.JsonIdentityInfo; import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.JsonIdentityReference; import com.fasterxml.jackson.annotation.JsonIdentityReference;
import org.libreccm.portation.Portable;
import javax.persistence.*;
import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient; import javax.xml.bind.annotation.XmlTransient;
import java.io.Serializable; import java.io.Serializable;
import java.util.Objects; import java.util.Objects;
import static org.libreccm.core.CoreConstants.CORE_XML_NS; import static org.libreccm.core.CoreConstants.CORE_XML_NS;
import static org.libreccm.core.CoreConstants.DB_SCHEMA; import static org.libreccm.core.CoreConstants.DB_SCHEMA;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
import org.libreccm.imexport.Exportable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
/** /**
* A association class representing the assoication between a {@link User} and * A association class representing the association between a {@link User} and a
* a {@code Group}. * {@code Group}.
* *
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a> * @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/ */
@Entity @Entity
@Table(name = "GROUP_MEMBERSHIPS", schema = DB_SCHEMA) @Table(name = "GROUP_MEMBERSHIPS", schema = DB_SCHEMA)
@NamedQueries({ @NamedQueries({
@NamedQuery(name = "GroupMembership.findByUuid",
query = "SELECT m FROM GroupMembership m WHERE m.uuid = :uuid")
,
@NamedQuery(name = "GroupMembership.findByGroupAndUser", @NamedQuery(name = "GroupMembership.findByGroupAndUser",
query = "SELECT m FROM GroupMembership m " query = "SELECT m FROM GroupMembership m "
+ "WHERE m.member = :member AND m.group = :group")}) + "WHERE m.member = :member AND m.group = :group")})
@XmlRootElement(name = "group-membership", namespace = CORE_XML_NS) @XmlRootElement(name = "group-membership", namespace = CORE_XML_NS)
@JsonIdentityInfo(generator = GroupMembershipIdGenerator.class, @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class,
property = "customMemId") property = "uuid")
public class GroupMembership implements Serializable, Portable { public class GroupMembership implements Serializable, Exportable {
private static final long serialVersionUID = 83192968306850665L; private static final long serialVersionUID = 83192968306850665L;
@ -57,6 +73,10 @@ public class GroupMembership implements Serializable, Portable {
@XmlElement(name = "membership-id", namespace = CORE_XML_NS) @XmlElement(name = "membership-id", namespace = CORE_XML_NS)
private long membershipId; private long membershipId;
@Column(name = "UUID", unique = true, nullable = false)
@XmlElement(name = "uuid", namespace = CORE_XML_NS)
private String uuid;
@ManyToOne @ManyToOne
@JoinColumn(name = "GROUP_ID") @JoinColumn(name = "GROUP_ID")
@XmlTransient @XmlTransient
@ -77,6 +97,15 @@ public class GroupMembership implements Serializable, Portable {
this.membershipId = membershipId; this.membershipId = membershipId;
} }
@Override
public String getUuid() {
return uuid;
}
protected void setUuid(final String uuid) {
this.uuid = uuid;
}
public Group getGroup() { public Group getGroup() {
return group; return group;
} }

View File

@ -1,71 +0,0 @@
/*
* Copyright (C) 2015 LibreCCM Foundation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package org.libreccm.security;
import com.fasterxml.jackson.annotation.ObjectIdGenerator;
/**
* @author <a href="mailto:tosmers@uni-bremen.de>Tobias Osmers</a>
* @version created on 3/23/17
*/
public class GroupMembershipIdGenerator extends ObjectIdGenerator<String> {
private static final long serialVersionUID = 5256221797846627835L;
@Override
public Class<?> getScope() {
return GroupMembership.class;
}
@Override
public boolean canUseFor(final ObjectIdGenerator<?> gen) {
return gen instanceof GroupMembershipIdGenerator;
}
@Override
public ObjectIdGenerator<String> forScope(final Class<?> scope) {
return this;
}
@Override
public ObjectIdGenerator<String> newForSerialization(final Object context) {
return this;
}
@Override
public IdKey key(final Object key) {
if (key == null) {
return null;
}
return new IdKey(GroupMembership.class, GroupMembership.class, key);
}
@Override
public String generateId(final Object forPojo) {
if (!(forPojo instanceof GroupMembership)) {
throw new IllegalArgumentException(
"Only GroupMembership instances are supported.");
}
final GroupMembership membership = (GroupMembership) forPojo;
return String.format("{%s}{%s}",
membership.getGroup().getName(),
membership.getMember().getName());
}
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2015 LibreCCM Foundation. * Copyright (C) 2018 LibreCCM Foundation.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@ -18,37 +18,37 @@
*/ */
package org.libreccm.security; package org.libreccm.security;
import org.libreccm.portation.AbstractMarshaller; import org.libreccm.imexport.AbstractEntityImExporter;
import org.libreccm.portation.Marshals; import org.libreccm.imexport.DependsOn;
import org.libreccm.imexport.Processes;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject; import javax.inject.Inject;
import javax.persistence.EntityManager; import javax.persistence.EntityManager;
import javax.transaction.Transactional; import javax.transaction.Transactional;
/** /**
* @author <a href="mailto:tosmers@uni-bremen.de>Tobias Osmers</a> *
* @version created on 11/7/16 * @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/ */
@RequestScoped @Processes(GroupMembership.class)
@Marshals(GroupMembership.class) @DependsOn({User.class, Group.class})
public class GroupMembershipMarshaller extends AbstractMarshaller<GroupMembership> { public class GroupMembershipImExporter extends AbstractEntityImExporter<GroupMembership> {
private static final long serialVersionUID = -1920271635191667015L;
@Inject @Inject
private EntityManager entityManager; private EntityManager entityManager;
@Override @Override
protected Class<GroupMembership> getObjectClass() { protected Class<GroupMembership> getEntityClass() {
return GroupMembership.class; return GroupMembership.class;
} }
@Override @Override
@Transactional(Transactional.TxType.REQUIRED) @Transactional(Transactional.TxType.REQUIRED)
protected void insertIntoDb(final GroupMembership portableObject) { protected void saveImportedEntity(final GroupMembership entity) {
portableObject.setMembershipId(portableObject.getMembershipId() * -1);
entityManager.merge(portableObject); entityManager.persist(entity);
entityManager.flush();
} }
} }

View File

@ -61,6 +61,19 @@ public class GroupRepository extends AbstractEntityRepository<Long, Group> {
return entity.getPartyId() == 0; return entity.getPartyId() == 0;
} }
public Optional<Group> findByUuid(final String uuid) {
final TypedQuery<Group> query = getEntityManager()
.createNamedQuery("Group.findByUuid", Group.class);
query.setParameter("uuid", uuid);
final List<Group> result = query.getResultList();
if (result.isEmpty()) {
return Optional.empty();
} else {
return Optional.of(result.get(0));
}
}
/** /**
* Finds a group by its name. * Finds a group by its name.
* *

View File

@ -18,6 +18,8 @@
*/ */
package org.libreccm.security; package org.libreccm.security;
import static org.libreccm.core.CoreConstants.*;
import com.fasterxml.jackson.annotation.JsonIdentityInfo; import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.ObjectIdGenerators; import com.fasterxml.jackson.annotation.ObjectIdGenerators;
@ -33,9 +35,6 @@ import java.util.HashSet;
import java.util.Objects; import java.util.Objects;
import java.util.Set; import java.util.Set;
import static org.libreccm.core.CoreConstants.CORE_XML_NS;
import static org.libreccm.core.CoreConstants.DB_SCHEMA;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.GeneratedValue; import javax.persistence.GeneratedValue;
@ -62,6 +61,10 @@ import javax.persistence.Table;
@Table(name = "PARTIES", schema = DB_SCHEMA) @Table(name = "PARTIES", schema = DB_SCHEMA)
@Inheritance(strategy = InheritanceType.JOINED) @Inheritance(strategy = InheritanceType.JOINED)
@NamedQueries({ @NamedQueries({
@NamedQuery(
name = "Party.findByUuid",
query = "SELECT p FROM Party p WHERE p.uuid = :uuid"
),
@NamedQuery( @NamedQuery(
name = "Party.findByName", name = "Party.findByName",
query = "SELECT p FROM Party p WHERE p.name = :name") query = "SELECT p FROM Party p WHERE p.name = :name")
@ -86,7 +89,7 @@ import javax.persistence.Table;
}) })
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class,
resolver = PartyIdResolver.class, resolver = PartyIdResolver.class,
property = "name") property = "uuid")
public class Party implements Serializable { public class Party implements Serializable {
private static final long serialVersionUID = 3319997992281332204L; private static final long serialVersionUID = 3319997992281332204L;
@ -94,9 +97,11 @@ public class Party implements Serializable {
@Id @Id
@Column(name = "PARTY_ID") @Column(name = "PARTY_ID")
@GeneratedValue(strategy = GenerationType.AUTO) @GeneratedValue(strategy = GenerationType.AUTO)
@XmlElement(name = "party-id", namespace = CORE_XML_NS)
private long partyId; private long partyId;
@Column(name = "UUID", unique = true, nullable = false) @Column(name = "UUID", unique = true, nullable = false)
@XmlElement(name = "uuid", namespace = CORE_XML_NS)
private String uuid; private String uuid;
/** /**
@ -105,6 +110,7 @@ public class Party implements Serializable {
*/ */
@Column(name = "NAME", length = 256, nullable = false) @Column(name = "NAME", length = 256, nullable = false)
@NotNull @NotNull
@XmlElement(name = "name", namespace = CORE_XML_NS)
// @Pattern(regexp = "[a-zA-Z0-9\\-_\\.]*") // @Pattern(regexp = "[a-zA-Z0-9\\-_\\.]*")
private String name; private String name;

View File

@ -26,7 +26,7 @@ import javax.enterprise.context.RequestScoped;
import java.io.Serializable; import java.io.Serializable;
/** /**
* @author <a href="mailto:tosmers@uni-bremen.de>Tobias Osmers</a> * @author <a href="mailto:tosmers@uni-bremen.de">Tobias Osmers</a>
* @version created on 3/23/17 * @version created on 3/23/17
*/ */
@RequestScoped @RequestScoped
@ -43,14 +43,15 @@ public class PartyIdResolver implements Serializable, ObjectIdResolver {
@Override @Override
public Object resolveId(final ObjectIdGenerator.IdKey id) { public Object resolveId(final ObjectIdGenerator.IdKey id) {
final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final PartyRepository partyRepository = cdiUtil final PartyRepository partyRepository = cdiUtil
.findBean(PartyRepository.class); .findBean(PartyRepository.class);
return partyRepository return partyRepository
.findByName(id.key.toString()) .findByUuid(id.key.toString())
.orElseThrow(() -> new IllegalArgumentException(String .orElseThrow(() -> new IllegalArgumentException(String
.format("No Party with name %s in the database.", .format("No Party with uuid %s in the database.",
id.key.toString()))); id.key.toString())));
} }

View File

@ -67,6 +67,20 @@ public class PartyRepository extends AbstractEntityRepository<Long, Party> {
party.setUuid(UUID.randomUUID().toString()); party.setUuid(UUID.randomUUID().toString());
} }
public Optional<Party> findByUuid(final String uuid) {
final TypedQuery<Party> query = getEntityManager().createNamedQuery(
"Party.findByUuid", Party.class);
query.setParameter("uuid", uuid);
final List<Party> result = query.getResultList();
if (result.isEmpty()) {
return Optional.empty();
} else {
return Optional.of(result.get(0));
}
}
/** /**
* Finds a {@link Party} (which can be a user or group) by its name. * Finds a {@link Party} (which can be a user or group) by its name.
* *

View File

@ -24,13 +24,13 @@ import org.hibernate.search.annotations.ContainedIn;
import org.hibernate.search.annotations.Field; import org.hibernate.search.annotations.Field;
import org.hibernate.search.annotations.IndexedEmbedded; import org.hibernate.search.annotations.IndexedEmbedded;
import org.libreccm.core.CcmObject; import org.libreccm.core.CcmObject;
import org.libreccm.portation.Portable;
import javax.persistence.*; import javax.persistence.*;
import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlRootElement;
import java.io.Serializable; import java.io.Serializable;
import java.util.Date; import java.util.Date;
import java.util.Objects; import java.util.Objects;
@ -38,6 +38,9 @@ import java.util.Objects;
import static org.libreccm.core.CoreConstants.CORE_XML_NS; import static org.libreccm.core.CoreConstants.CORE_XML_NS;
import static org.libreccm.core.CoreConstants.DB_SCHEMA; import static org.libreccm.core.CoreConstants.DB_SCHEMA;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
import org.libreccm.imexport.Exportable;
/** /**
* A permission grants a privilege on an object or system wide to {@link Role}. * A permission grants a privilege on an object or system wide to {@link Role}.
* *
@ -46,6 +49,9 @@ import static org.libreccm.core.CoreConstants.DB_SCHEMA;
@Entity @Entity
@Table(name = "PERMISSIONS", schema = DB_SCHEMA) @Table(name = "PERMISSIONS", schema = DB_SCHEMA)
@NamedQueries({ @NamedQueries({
@NamedQuery(name = "Permission.findByUuid",
query = "SELECT p FROM Permission p WHERE p.uuid = :uuid")
,
@NamedQuery(name = "Permission.findByCustomPermId", @NamedQuery(name = "Permission.findByCustomPermId",
query = "SELECT p FROM Permission p " query = "SELECT p FROM Permission p "
+ "WHERE p.grantedPrivilege = :privilege " + "WHERE p.grantedPrivilege = :privilege "
@ -93,10 +99,10 @@ import static org.libreccm.core.CoreConstants.DB_SCHEMA;
}) })
@XmlRootElement(name = "permission", namespace = CORE_XML_NS) @XmlRootElement(name = "permission", namespace = CORE_XML_NS)
@XmlAccessorType(XmlAccessType.FIELD) @XmlAccessorType(XmlAccessType.FIELD)
@JsonIdentityInfo(generator = PermissionIdGenerator.class, @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class,
resolver = PermissionIdResolver.class, resolver = PermissionIdResolver.class,
property = "customPermId") property = "uuid")
public class Permission implements Serializable, Portable { public class Permission implements Serializable, Exportable {
private static final long serialVersionUID = -5178045844045517958L; private static final long serialVersionUID = -5178045844045517958L;
@ -109,6 +115,10 @@ public class Permission implements Serializable, Portable {
@XmlElement(name = "permission-id", namespace = CORE_XML_NS) @XmlElement(name = "permission-id", namespace = CORE_XML_NS)
private long permissionId; private long permissionId;
@Column(name = "UUID", unique = true, nullable = false)
@XmlElement(name = "uuid", namespace = CORE_XML_NS)
private String uuid;
/** /**
* The granted privilege. * The granted privilege.
*/ */
@ -192,6 +202,15 @@ public class Permission implements Serializable, Portable {
this.permissionId = permissionId; this.permissionId = permissionId;
} }
@Override
public String getUuid() {
return uuid;
}
protected void setUuid(final String uuid) {
this.uuid = uuid;
}
public String getGrantedPrivilege() { public String getGrantedPrivilege() {
return grantedPrivilege; return grantedPrivilege;
} }

View File

@ -1,78 +0,0 @@
/*
* Copyright (C) 2015 LibreCCM Foundation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package org.libreccm.security;
import com.fasterxml.jackson.annotation.ObjectIdGenerator;
/**
* @author <a href="mailto:tosmers@uni-bremen.de>Tobias Osmers</a>
* @version created on 3/23/17
*/
public class PermissionIdGenerator extends ObjectIdGenerator<String> {
private static final long serialVersionUID = -8762745860290577542L;
@Override
public Class<?> getScope() {
return Permission.class;
}
@Override
public boolean canUseFor(final ObjectIdGenerator<?> gen) {
return gen instanceof PermissionIdGenerator;
}
@Override
public ObjectIdGenerator<String> forScope(final Class<?> scope) {
return this;
}
@Override
public ObjectIdGenerator<String> newForSerialization(final Object context) {
return this;
}
@Override
public IdKey key(final Object key) {
if (key == null) {
return null;
}
return new IdKey(Permission.class, Permission.class, key);
}
@Override
public String generateId(final Object forPojo) {
if (!(forPojo instanceof Permission)) {
throw new IllegalArgumentException(
"Only Permission instances are supported.");
}
final Permission permission = (Permission) forPojo;
if (permission.getGrantee() == null &&
permission.getObject() == null) {
throw new IllegalStateException();
}
return String.join("_",
permission.getGrantedPrivilege(),
String.valueOf(permission.getGrantee().getName()),
String.valueOf(permission.getObject().getUuid())
);
}
}

View File

@ -21,13 +21,10 @@ package org.libreccm.security;
import com.fasterxml.jackson.annotation.ObjectIdGenerator; import com.fasterxml.jackson.annotation.ObjectIdGenerator;
import com.fasterxml.jackson.annotation.ObjectIdResolver; import com.fasterxml.jackson.annotation.ObjectIdResolver;
import org.libreccm.cdi.utils.CdiUtil; import org.libreccm.cdi.utils.CdiUtil;
import org.libreccm.core.CcmObject;
import org.libreccm.core.CcmObjectRepository;
import org.libreccm.core.UnexpectedErrorException;
import javax.enterprise.context.RequestScoped; import javax.enterprise.context.RequestScoped;
import java.io.Serializable; import java.io.Serializable;
import java.util.Optional;
/** /**
* @author <a href="mailto:tosmers@uni-bremen.de>Tobias Osmers</a> * @author <a href="mailto:tosmers@uni-bremen.de>Tobias Osmers</a>
@ -47,43 +44,16 @@ public class PermissionIdResolver implements Serializable, ObjectIdResolver {
@Override @Override
public Object resolveId(final ObjectIdGenerator.IdKey id) { public Object resolveId(final ObjectIdGenerator.IdKey id) {
final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final CcmObjectRepository ccmObjectRepository = cdiUtil
.findBean(CcmObjectRepository.class);
final RoleRepository roleRepository = cdiUtil
.findBean(RoleRepository.class);
final PermissionRepository permissionRepository = cdiUtil final PermissionRepository permissionRepository = cdiUtil
.findBean(PermissionRepository.class); .findBean(PermissionRepository.class);
String[] customPermId = id.key.toString().split("_"); return permissionRepository
.findByUuid(id.key.toString())
String privilege = customPermId[0]; .orElseThrow(() -> new IllegalArgumentException(String
final String granteeName = customPermId[1]; .format("No Permission with UUID %s in the database.",
final String objectUuid = customPermId[2]; id.key.toString())));
final Optional<CcmObject> object = ccmObjectRepository
.findObjectByUuid(objectUuid);
final Optional<Role> grantee = roleRepository
.findByName(granteeName);
if (!grantee.isPresent()) {
throw new UnexpectedErrorException(String.format(
"Role with id \"%s\" was not found in the database," +
" but has been associated with a permission.",
granteeName));
}
Optional<Permission> permission = permissionRepository
.findByCustomPermId(privilege,
grantee.get(),
object.orElse(null));
if (!permission.isPresent()) {
throw new UnexpectedErrorException(String.format(
"Permission with privilege \"%s\", grantee \"%s and " +
"object \"%s\" was not found in the database.",
privilege, grantee.toString(), object.toString()));
}
return permission.get();
} }
@Override @Override

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2015 LibreCCM Foundation. * Copyright (C) 2018 LibreCCM Foundation.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@ -18,33 +18,36 @@
*/ */
package org.libreccm.security; package org.libreccm.security;
import org.libreccm.portation.AbstractMarshaller; import org.libreccm.imexport.AbstractEntityImExporter;
import org.libreccm.portation.Marshals; import org.libreccm.imexport.DependsOn;
import org.libreccm.imexport.Processes;
import javax.enterprise.context.RequestScoped; import javax.enterprise.context.RequestScoped;
import javax.inject.Inject; import javax.inject.Inject;
import javax.transaction.Transactional;
/** /**
* @author <a href="mailto:tosmers@uni-bremen.de>Tobias Osmers</a> *
* @version created on 11/7/16 * @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/ */
@RequestScoped @RequestScoped
@Marshals(User.class) @Processes(Permission.class)
public class UserMarshaller extends AbstractMarshaller<User> { @DependsOn({Role.class})
private static final long serialVersionUID = -7857346915894246160L; public class PermissionImExporter extends AbstractEntityImExporter<Permission>{
@Inject @Inject
private UserRepository userRepository; private PermissionRepository permissionRepository;
@Override @Override
protected Class<User> getObjectClass() { protected Class<Permission> getEntityClass() {
return User.class; return Permission.class;
} }
@Override @Override
@Transactional(Transactional.TxType.REQUIRED) protected void saveImportedEntity(final Permission entity) {
protected void insertIntoDb(User portableObject) {
userRepository.save(portableObject); permissionRepository.save(entity);
} }
} }

View File

@ -23,7 +23,9 @@ import org.libreccm.core.AbstractEntityRepository;
import javax.enterprise.context.RequestScoped; import javax.enterprise.context.RequestScoped;
import javax.persistence.NoResultException; import javax.persistence.NoResultException;
import javax.persistence.TypedQuery; import javax.persistence.TypedQuery;
import java.util.Optional; import java.util.Optional;
import java.util.UUID;
/** /**
* A repository class for {@link Permission}. * A repository class for {@link Permission}.
@ -53,13 +55,27 @@ public class PermissionRepository
} }
@Override @Override
public boolean isNew(Permission entity) { public boolean isNew(final Permission entity) {
if (entity == null) { if (entity == null) {
throw new IllegalArgumentException("Can't save null"); throw new IllegalArgumentException("Can't save null");
} }
return entity.getPermissionId() == 0; return entity.getPermissionId() == 0;
} }
@Override
public void initNewEntity(final Permission permission) {
permission.setUuid(UUID.randomUUID().toString());
}
public Optional<Permission> findByUuid(final String uuid) {
final TypedQuery<Permission> query = getEntityManager()
.createNamedQuery("Permission.findByUuid", Permission.class);
query.setParameter("uuid", uuid);
return getSingleResult(query);
}
/** /**
* Finds a {@link Permission} by the privilege, the grantee and the object. * Finds a {@link Permission} by the privilege, the grantee and the object.
* Where the grantee has been granted the given privilege on the given * Where the grantee has been granted the given privilege on the given

View File

@ -24,17 +24,45 @@ import com.fasterxml.jackson.annotation.ObjectIdGenerators;
import org.hibernate.search.annotations.Field; import org.hibernate.search.annotations.Field;
import org.hibernate.validator.constraints.NotBlank; import org.hibernate.validator.constraints.NotBlank;
import org.libreccm.l10n.LocalizedString; import org.libreccm.l10n.LocalizedString;
import org.libreccm.portation.Portable;
import org.libreccm.workflow.TaskAssignment; import org.libreccm.workflow.TaskAssignment;
import javax.persistence.*;
import javax.xml.bind.annotation.*;
import java.io.Serializable;
import java.util.*;
import static org.libreccm.core.CoreConstants.CORE_XML_NS; import static org.libreccm.core.CoreConstants.CORE_XML_NS;
import static org.libreccm.core.CoreConstants.DB_SCHEMA; import static org.libreccm.core.CoreConstants.DB_SCHEMA;
import org.libreccm.imexport.Exportable;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import javax.persistence.AssociationOverride;
import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.NamedAttributeNode;
import javax.persistence.NamedEntityGraph;
import javax.persistence.NamedEntityGraphs;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
/** /**
* A role is basically a collection a {@link Permission}s and {@code Task}s. * A role is basically a collection a {@link Permission}s and {@code Task}s.
* *
@ -43,6 +71,8 @@ import static org.libreccm.core.CoreConstants.DB_SCHEMA;
@Entity @Entity
@Table(name = "CCM_ROLES", schema = DB_SCHEMA) @Table(name = "CCM_ROLES", schema = DB_SCHEMA)
@NamedQueries({ @NamedQueries({
@NamedQuery(name = "Role.findByUuid",
query = "SELECT r FROM Role r WHERE r.uuid = :uuid"),
@NamedQuery(name = "Role.findByName", @NamedQuery(name = "Role.findByName",
query = "SELECT r FROM Role r " query = "SELECT r FROM Role r "
+ "WHERE r.name = :name") + "WHERE r.name = :name")
@ -118,8 +148,8 @@ import static org.libreccm.core.CoreConstants.DB_SCHEMA;
@SuppressWarnings({"PMD.ShortClassName", "PMD.TooManyMethods"}) @SuppressWarnings({"PMD.ShortClassName", "PMD.TooManyMethods"})
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class,
resolver = RoleIdResolver.class, resolver = RoleIdResolver.class,
property = "name") property = "uuid")
public class Role implements Serializable, Portable { public class Role implements Serializable, Exportable {
private static final long serialVersionUID = -7121296514181469687L; private static final long serialVersionUID = -7121296514181469687L;
@ -134,6 +164,10 @@ public class Role implements Serializable, Portable {
@XmlElement(name = "role-id", namespace = CORE_XML_NS) @XmlElement(name = "role-id", namespace = CORE_XML_NS)
private long roleId; private long roleId;
@Column(name = "UUID", unique = true, nullable = false)
@XmlElement(name = "uuid", namespace = CORE_XML_NS)
private String uuid;
/** /**
* The name of the role. May only contain the letters a to z, A to Z, the * The name of the role. May only contain the letters a to z, A to Z, the
* numbers 0 to 9, the {@code -} (dash) and the {@code _} (underscore). * numbers 0 to 9, the {@code -} (dash) and the {@code _} (underscore).
@ -194,6 +228,15 @@ public class Role implements Serializable, Portable {
this.roleId = roleId; this.roleId = roleId;
} }
@Override
public String getUuid() {
return uuid;
}
protected void setUuid(final String uuid) {
this.uuid = uuid;
}
public String getName() { public String getName() {
return name; return name;
} }

View File

@ -48,9 +48,9 @@ public class RoleIdResolver implements Serializable, ObjectIdResolver {
.findBean(RoleRepository.class); .findBean(RoleRepository.class);
return roleRepository return roleRepository
.findByName(id.key.toString()) .findByUuid(id.key.toString())
.orElseThrow(() -> new IllegalArgumentException(String .orElseThrow(() -> new IllegalArgumentException(String
.format("No Role with name %s in the database.", .format("No Role with uuid %s in the database.",
id.key.toString()))); id.key.toString())));
} }

View File

@ -16,25 +16,33 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA * MA 02110-1301 USA
*/ */
package org.libreccm.imexport; package org.libreccm.security;
import javax.enterprise.context.RequestScoped; import org.libreccm.imexport.AbstractEntityImExporter;
import javax.json.JsonObject; import org.libreccm.imexport.Processes;
import javax.inject.Inject;
/** /**
* Interface for importers/exporters. Implementations must be annotated with
* {@link Procsses} to register the implementation in the Import/Export service.
*
* Implementations must also be CDI beans. It is recommended that the beans
* are {@link RequestScoped}.
* *
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a> * @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
* @param <T> The type of the entity which is processed by the implementation.
*/ */
public interface EntityImExporter<T extends Exportable> { @Processes(Role.class)
public class RoleImExporter extends AbstractEntityImExporter<Role> {
T importEntity(JsonObject data); @Inject
private RoleRepository roleRepository;
JsonObject exportEntity(Exportable entity); @Override
protected Class<Role> getEntityClass() {
return Role.class;
}
@Override
protected void saveImportedEntity(final Role entity) {
roleRepository.save(entity);
}
} }

View File

@ -33,6 +33,7 @@ import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
@ -83,6 +84,7 @@ public class RoleManager implements Serializable {
} }
final RoleMembership membership = new RoleMembership(); final RoleMembership membership = new RoleMembership();
membership.setUuid(UUID.randomUUID().toString());
membership.setRole(role); membership.setRole(role);
membership.setMember(party); membership.setMember(party);

View File

@ -1,50 +0,0 @@
/*
* Copyright (C) 2015 LibreCCM Foundation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package org.libreccm.security;
import org.libreccm.portation.AbstractMarshaller;
import org.libreccm.portation.Marshals;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.transaction.Transactional;
/**
* @author <a href="mailto:tosmers@uni-bremen.de>Tobias Osmers</a>
* @version created on 11/7/16
*/
@RequestScoped
@Marshals(Role.class)
public class RoleMarshaller extends AbstractMarshaller<Role> {
private static final long serialVersionUID = -2150833120444479902L;
@Inject
private RoleRepository roleRepository;
@Override
protected Class<Role> getObjectClass() {
return Role.class;
}
@Override
@Transactional(Transactional.TxType.REQUIRED)
protected void insertIntoDb(Role portableObject) {
roleRepository.save(portableObject);
}
}

View File

@ -20,18 +20,31 @@ package org.libreccm.security;
import com.fasterxml.jackson.annotation.JsonIdentityInfo; import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.JsonIdentityReference; import com.fasterxml.jackson.annotation.JsonIdentityReference;
import org.libreccm.portation.Portable;
import javax.persistence.*;
import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient; import javax.xml.bind.annotation.XmlTransient;
import java.io.Serializable; import java.io.Serializable;
import java.util.Objects; import java.util.Objects;
import static org.libreccm.core.CoreConstants.CORE_XML_NS; import static org.libreccm.core.CoreConstants.CORE_XML_NS;
import static org.libreccm.core.CoreConstants.DB_SCHEMA; import static org.libreccm.core.CoreConstants.DB_SCHEMA;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
import org.libreccm.imexport.Exportable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
/** /**
* Association class representing the association between a {@link Role} and a * Association class representing the association between a {@link Role} and a
* {@code Party}. * {@code Party}.
@ -41,14 +54,17 @@ import static org.libreccm.core.CoreConstants.DB_SCHEMA;
@Entity @Entity
@Table(name = "ROLE_MEMBERSHIPS", schema = DB_SCHEMA) @Table(name = "ROLE_MEMBERSHIPS", schema = DB_SCHEMA)
@NamedQueries({ @NamedQueries({
@NamedQuery(name = "RoleMembership.findByUuid",
query = "SELECT m FROM RoleMembership m WHERE m.uuid = :uuid")
,
@NamedQuery(name = "RoleMembership.findByRoleAndMember", @NamedQuery(name = "RoleMembership.findByRoleAndMember",
query = "SELECT m FROM RoleMembership m " query = "SELECT m FROM RoleMembership m "
+ "WHERE m.member = :member AND m.role = :role") + "WHERE m.member = :member AND m.role = :role")
}) })
@XmlRootElement(name = "role-membership", namespace = CORE_XML_NS) @XmlRootElement(name = "role-membership", namespace = CORE_XML_NS)
@JsonIdentityInfo(generator = RoleMembershipIdGenerator.class, @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class,
property = "customMemId") property = "uuid")
public class RoleMembership implements Serializable, Portable { public class RoleMembership implements Serializable, Exportable {
private static final long serialVersionUID = -3049727720697964793L; private static final long serialVersionUID = -3049727720697964793L;
@ -58,6 +74,10 @@ public class RoleMembership implements Serializable, Portable {
@XmlElement(name = "membership-id", namespace = CORE_XML_NS) @XmlElement(name = "membership-id", namespace = CORE_XML_NS)
private long membershipId; private long membershipId;
@Column(name = "UUID", unique = true, nullable = false)
@XmlElement(name = "uuid", namespace = CORE_XML_NS)
private String uuid;
@ManyToOne @ManyToOne
@JoinColumn(name = "ROLE_ID") @JoinColumn(name = "ROLE_ID")
@XmlTransient @XmlTransient
@ -78,6 +98,15 @@ public class RoleMembership implements Serializable, Portable {
this.membershipId = membershipId; this.membershipId = membershipId;
} }
@Override
public String getUuid() {
return uuid;
}
protected void setUuid(final String uuid) {
this.uuid = uuid;
}
public Role getRole() { public Role getRole() {
return role; return role;
} }

View File

@ -1,71 +0,0 @@
/*
* Copyright (C) 2015 LibreCCM Foundation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package org.libreccm.security;
import com.fasterxml.jackson.annotation.ObjectIdGenerator;
/**
* @author <a href="mailto:tosmers@uni-bremen.de>Tobias Osmers</a>
* @version created on 3/23/17
*/
public class RoleMembershipIdGenerator extends ObjectIdGenerator<String> {
private static final long serialVersionUID = 801410727263488529L;
@Override
public Class<?> getScope() {
return RoleMembership.class;
}
@Override
public boolean canUseFor(final ObjectIdGenerator<?> gen) {
return gen instanceof RoleMembershipIdGenerator;
}
@Override
public ObjectIdGenerator<String> forScope(final Class<?> scope) {
return this;
}
@Override
public ObjectIdGenerator<String> newForSerialization(final Object context) {
return this;
}
@Override
public IdKey key(final Object key) {
if (key == null) {
return null;
}
return new IdKey(RoleMembership.class, RoleMembership.class, key);
}
@Override
public String generateId(final Object forPojo) {
if (!(forPojo instanceof RoleMembership)) {
throw new IllegalArgumentException(
"Only RoleMembership instances are supported.");
}
final RoleMembership membership = (RoleMembership) forPojo;
return String.format("{%s}{%s}",
membership.getRole().getName(),
membership.getMember().getName());
}
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2015 LibreCCM Foundation. * Copyright (C) 2018 LibreCCM Foundation.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@ -18,38 +18,37 @@
*/ */
package org.libreccm.security; package org.libreccm.security;
import org.libreccm.portation.AbstractMarshaller; import org.libreccm.imexport.AbstractEntityImExporter;
import org.libreccm.portation.Marshals; import org.libreccm.imexport.DependsOn;
import org.libreccm.imexport.Processes;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject; import javax.inject.Inject;
import javax.persistence.EntityManager; import javax.persistence.EntityManager;
import javax.transaction.Transactional; import javax.transaction.Transactional;
/** /**
* @author <a href="mailto:tosmers@uni-bremen.de">Tobias Osmers</a> *
* @version created on 11/7/16 * @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/ */
@RequestScoped @Processes(RoleMembership.class)
@Marshals(Permission.class) @DependsOn({User.class, Group.class, Role.class})
public class PermissionMarshaller extends AbstractMarshaller<Permission> { public class RoleMembershipImExporter
private static final long serialVersionUID = -5145925775270121916L; extends AbstractEntityImExporter<RoleMembership>{
@Inject @Inject
private EntityManager entityManager; private EntityManager entityManager;
@Override @Override
protected Class<Permission> getObjectClass() { protected Class<RoleMembership> getEntityClass() {
return Permission.class;
return RoleMembership.class;
} }
@Override @Override
@Transactional(Transactional.TxType.REQUIRED) @Transactional(Transactional.TxType.REQUIRED)
protected void insertIntoDb(Permission portableObject) { protected void saveImportedEntity(final RoleMembership entity) {
if (portableObject.getPermissionId() == 0) {
entityManager.persist(portableObject); entityManager.persist(entity);
} else {
entityManager.merge(portableObject);
}
} }
} }

View File

@ -1,58 +0,0 @@
/*
* Copyright (C) 2015 LibreCCM Foundation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package org.libreccm.security;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.libreccm.portation.AbstractMarshaller;
import org.libreccm.portation.Marshals;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.transaction.Transactional;
/**
* @author <a href="mailto:tosmers@uni-bremen.de">Tobias Osmers</a>
* @version created on 11/7/16
*/
@RequestScoped
@Marshals(RoleMembership.class)
public class RoleMembershipMarshaller extends AbstractMarshaller<RoleMembership> {
private static final long serialVersionUID = 1304404004268502935L;
private static final Logger LOGGER = LogManager.getLogger(RoleMembershipMarshaller.class);
@Inject
private EntityManager entityManager;
@Override
protected Class<RoleMembership> getObjectClass() {
return RoleMembership.class;
}
@Override
@Transactional(Transactional.TxType.REQUIRED)
protected void insertIntoDb(final RoleMembership portableObject) {
portableObject.setMembershipId(portableObject.getMembershipId() * -1);
entityManager.merge(portableObject);
entityManager.flush();
}
}

View File

@ -26,8 +26,10 @@ import javax.enterprise.context.RequestScoped;
import javax.persistence.NoResultException; import javax.persistence.NoResultException;
import javax.persistence.TypedQuery; import javax.persistence.TypedQuery;
import javax.transaction.Transactional; import javax.transaction.Transactional;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.UUID;
/** /**
* Repository class for {@link Role} entities. * Repository class for {@link Role} entities.
@ -62,12 +64,28 @@ public class RoleRepository extends AbstractEntityRepository<Long, Role> {
return entity.getRoleId() == 0; return entity.getRoleId() == 0;
} }
@Override
public void initNewEntity(final Role role) {
role.setUuid(UUID.randomUUID().toString());
}
public long count() { public long count() {
final TypedQuery<Long> query = getEntityManager().createNamedQuery( final TypedQuery<Long> query = getEntityManager().createNamedQuery(
"Role.count", Long.class); "Role.count", Long.class);
return query.getSingleResult(); return query.getSingleResult();
} }
public Optional<Role> findByUuid(final String uuid) {
final TypedQuery<Role> query = getEntityManager()
.createNamedQuery("Role.findByUuid", Role.class);
query.setParameter("uuid", uuid);
return getSingleResult(query);
}
/** /**
* Finds a role a its name. * Finds a role a its name.
* *

View File

@ -22,7 +22,6 @@ import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.ObjectIdGenerators; import com.fasterxml.jackson.annotation.ObjectIdGenerators;
import org.libreccm.core.EmailAddress; import org.libreccm.core.EmailAddress;
import org.libreccm.portation.Portable;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
@ -73,6 +72,9 @@ import javax.xml.bind.annotation.XmlTransient;
@Entity @Entity
@Table(name = "USERS", schema = DB_SCHEMA) @Table(name = "USERS", schema = DB_SCHEMA)
@NamedQueries({ @NamedQueries({
@NamedQuery(name = "User.findByUuid",
query = "SELECT u FROM User u WHERE u.uuid = :uuid")
,
@NamedQuery(name = "User.findByName", @NamedQuery(name = "User.findByName",
query = "SELECT u FROM User u WHERE u.name = :name " query = "SELECT u FROM User u WHERE u.name = :name "
+ "ORDER BY u.name, " + "ORDER BY u.name, "
@ -151,8 +153,8 @@ import javax.xml.bind.annotation.XmlTransient;
@SuppressWarnings({"PMD.ShortClassName", "PMD.LongVariable"}) @SuppressWarnings({"PMD.ShortClassName", "PMD.LongVariable"})
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class,
resolver = UserIdResolver.class, resolver = UserIdResolver.class,
property = "name") property = "uuid")
public class User extends Party implements Serializable, Exportable, Portable { public class User extends Party implements Serializable, Exportable {
private static final long serialVersionUID = 4035223413596611393L; private static final long serialVersionUID = 4035223413596611393L;

View File

@ -26,11 +26,12 @@ import javax.enterprise.context.RequestScoped;
import java.io.Serializable; import java.io.Serializable;
/** /**
* @author <a href="mailto:tosmers@uni-bremen.de>Tobias Osmers</a> * @author <a href="mailto:tosmers@uni-bremen.de">Tobias Osmers</a>
* @version created on 3/23/17 * @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/ */
@RequestScoped @RequestScoped
public class UserIdResolver implements Serializable, ObjectIdResolver { public class UserIdResolver implements Serializable, ObjectIdResolver {
private static final long serialVersionUID = -2541656707906049331L; private static final long serialVersionUID = -2541656707906049331L;
@Override @Override
@ -43,12 +44,13 @@ public class UserIdResolver implements Serializable, ObjectIdResolver {
@Override @Override
public Object resolveId(final ObjectIdGenerator.IdKey id) { public Object resolveId(final ObjectIdGenerator.IdKey id) {
final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final UserRepository userRepository = cdiUtil final UserRepository userRepository = cdiUtil
.findBean(UserRepository.class); .findBean(UserRepository.class);
return userRepository return userRepository
.findByName(id.key.toString()) .findByUuid(id.key.toString())
.orElseThrow(() -> new IllegalArgumentException(String .orElseThrow(() -> new IllegalArgumentException(String
.format("No User with name %s in the database.", .format("No User with name %s in the database.",
id.key.toString()))); id.key.toString())));

View File

@ -18,12 +18,12 @@
*/ */
package org.libreccm.security; package org.libreccm.security;
import org.libreccm.imexport.EntityImExporter; import org.libreccm.imexport.AbstractEntityImExporter;
import org.libreccm.imexport.Exportable;
import org.libreccm.imexport.Processes; import org.libreccm.imexport.Processes;
import javax.enterprise.context.RequestScoped; import javax.enterprise.context.RequestScoped;
import javax.json.JsonObject; import javax.inject.Inject;
import javax.transaction.Transactional;
/** /**
* *
@ -31,16 +31,21 @@ import javax.json.JsonObject;
*/ */
@RequestScoped @RequestScoped
@Processes(User.class) @Processes(User.class)
public class UserImExporter implements EntityImExporter<User> { public class UserImExporter extends AbstractEntityImExporter<User> {
@Inject
private UserRepository userRepository;
@Override @Override
public User importEntity(final JsonObject data) { protected Class<User> getEntityClass() {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. return User.class;
} }
@Override @Override
public JsonObject exportEntity(final Exportable entity) { @Transactional(Transactional.TxType.REQUIRED)
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. protected void saveImportedEntity(final User entity) {
userRepository.save(entity);
} }
} }

View File

@ -61,6 +61,14 @@ public class UserRepository extends AbstractEntityRepository<Long, User> {
return user.getPartyId() == 0; return user.getPartyId() == 0;
} }
public Optional<User> findByUuid(final String uuid) {
final TypedQuery<User> query = getEntityManager().createNamedQuery(
"User.findByUuid", User.class);
query.setParameter("uuid", uuid);
return getSingleResult(query);
}
/** /**
* Finds a user by its user name. * Finds a user by its user name.
* *

View File

@ -0,0 +1,5 @@
alter table CCM_CORE.ROLES
add column UUID varchar(255) not null;
alter table CCM_CORE.ROLES
add constraint UK_rfmsjqsq6kagolsod3ufkugll unique (UUID);

View File

@ -0,0 +1,6 @@
alter table CCM_CORE.PERMISSIONS
add column UUID varchar(255) not null;
alter table CCM_CORE.PERMISSIONS
add constraint UK_p50se7rdexv7xnkiqsl6ijyti unique (UUID);

View File

@ -0,0 +1,7 @@
alter table CCM_CORE.GROUP_MEMBERSHIPS
add column UUID varchar(255) not null;
alter table CCM_CORE.GROUP_MEMBERSHIPS
add constraint UK_kkdoia60bmiwhhdru169p3n9g unique (UUID);

View File

@ -0,0 +1,7 @@
alter table CCM_CORE.ROLE_MEMBERSHIPS
add column UUID varchar(255) not null;
alter table CCM_CORE.ROLE_MEMBERSHIPS
add constraint UK_82wdq214bfs99eii71fp50s97 unique (UUID);

View File

@ -0,0 +1,5 @@
alter table CCM_CORE.ROLES
add column UUID varchar(255) not null;
alter table CCM_CORE.ROLES
add constraint UK_rfmsjqsq6kagolsod3ufkugll unique (UUID);

View File

@ -0,0 +1,6 @@
alter table CCM_CORE.PERMISSIONS
add column UUID varchar(255) not null;
alter table CCM_CORE.PERMISSIONS
add constraint UK_p50se7rdexv7xnkiqsl6ijyti unique (UUID);

View File

@ -0,0 +1,7 @@
alter table CCM_CORE.GROUP_MEMBERSHIPS
add column UUID varchar(255) not null;
alter table CCM_CORE.GROUP_MEMBERSHIPS
add constraint UK_kkdoia60bmiwhhdru169p3n9g unique (UUID);

View File

@ -0,0 +1,7 @@
alter table CCM_CORE.ROLE_MEMBERSHIPS
add column UUID varchar(255) not null;
alter table CCM_CORE.ROLE_MEMBERSHIPS
add constraint UK_82wdq214bfs99eii71fp50s97 unique (UUID);

View File

@ -4,6 +4,7 @@ drop sequence if exists HIBERNATE_SEQUENCE;
create schema CCM_CORE; create schema CCM_CORE;
create table CCM_CORE.APPLICATIONS ( create table CCM_CORE.APPLICATIONS (
APPLICATION_TYPE varchar(1024) not null, APPLICATION_TYPE varchar(1024) not null,
PRIMARY_URL varchar(1024) not null, PRIMARY_URL varchar(1024) not null,
@ -94,6 +95,7 @@ drop sequence if exists HIBERNATE_SEQUENCE;
create table CCM_CORE.CCM_ROLES ( create table CCM_CORE.CCM_ROLES (
ROLE_ID bigint not null, ROLE_ID bigint not null,
NAME varchar(512) not null, NAME varchar(512) not null,
UUID varchar(255) not null,
primary key (ROLE_ID) primary key (ROLE_ID)
); );
@ -541,11 +543,11 @@ drop sequence if exists HIBERNATE_SEQUENCE;
SETTING_ID bigint not null, SETTING_ID bigint not null,
CONFIGURATION_CLASS varchar(512) not null, CONFIGURATION_CLASS varchar(512) not null,
NAME varchar(512) not null, NAME varchar(512) not null,
SETTING_VALUE_LONG bigint,
SETTING_VALUE_BIG_DECIMAL decimal(19,2), SETTING_VALUE_BIG_DECIMAL decimal(19,2),
SETTING_VALUE_BOOLEAN boolean, SETTING_VALUE_BOOLEAN boolean,
SETTING_VALUE_STRING varchar(1024),
SETTING_VALUE_DOUBLE double, SETTING_VALUE_DOUBLE double,
SETTING_VALUE_LONG bigint, SETTING_VALUE_STRING varchar(1024),
primary key (SETTING_ID) primary key (SETTING_ID)
); );
@ -771,6 +773,9 @@ drop sequence if exists HIBERNATE_SEQUENCE;
alter table CCM_CORE.CCM_OBJECTS alter table CCM_CORE.CCM_OBJECTS
add constraint UK_1cm71jlagvyvcnkqvxqyit3wx unique (UUID); add constraint UK_1cm71jlagvyvcnkqvxqyit3wx unique (UUID);
alter table CCM_CORE.CCM_ROLES
add constraint UK_rfmsjqsq6kagolsod3ufkugll unique (UUID);
alter table CCM_CORE.HOSTS alter table CCM_CORE.HOSTS
add constraint UK9ramlv6uxwt13v0wj7q0tucsx unique (SERVER_NAME, SERVER_PORT); add constraint UK9ramlv6uxwt13v0wj7q0tucsx unique (SERVER_NAME, SERVER_PORT);

View File

@ -2,8 +2,6 @@ drop schema if exists CCM_CORE cascade;
drop sequence if exists HIBERNATE_SEQUENCE; drop sequence if exists HIBERNATE_SEQUENCE;
create schema CCM_CORE;
create table CCM_CORE.APPLICATIONS ( create table CCM_CORE.APPLICATIONS (
APPLICATION_TYPE varchar(1024) not null, APPLICATION_TYPE varchar(1024) not null,
PRIMARY_URL varchar(1024) not null, PRIMARY_URL varchar(1024) not null,
@ -94,6 +92,7 @@ drop sequence if exists HIBERNATE_SEQUENCE;
create table CCM_CORE.CCM_ROLES ( create table CCM_CORE.CCM_ROLES (
ROLE_ID int8 not null, ROLE_ID int8 not null,
NAME varchar(512) not null, NAME varchar(512) not null,
UUID varchar(255) not null,
primary key (ROLE_ID) primary key (ROLE_ID)
); );
@ -541,11 +540,11 @@ drop sequence if exists HIBERNATE_SEQUENCE;
SETTING_ID int8 not null, SETTING_ID int8 not null,
CONFIGURATION_CLASS varchar(512) not null, CONFIGURATION_CLASS varchar(512) not null,
NAME varchar(512) not null, NAME varchar(512) not null,
SETTING_VALUE_LONG int8,
SETTING_VALUE_BIG_DECIMAL numeric(19, 2), SETTING_VALUE_BIG_DECIMAL numeric(19, 2),
SETTING_VALUE_BOOLEAN boolean, SETTING_VALUE_BOOLEAN boolean,
SETTING_VALUE_STRING varchar(1024),
SETTING_VALUE_DOUBLE float8, SETTING_VALUE_DOUBLE float8,
SETTING_VALUE_LONG int8, SETTING_VALUE_STRING varchar(1024),
primary key (SETTING_ID) primary key (SETTING_ID)
); );
@ -771,6 +770,9 @@ drop sequence if exists HIBERNATE_SEQUENCE;
alter table CCM_CORE.CCM_OBJECTS alter table CCM_CORE.CCM_OBJECTS
add constraint UK_1cm71jlagvyvcnkqvxqyit3wx unique (UUID); add constraint UK_1cm71jlagvyvcnkqvxqyit3wx unique (UUID);
alter table CCM_CORE.CCM_ROLES
add constraint UK_rfmsjqsq6kagolsod3ufkugll unique (UUID);
alter table CCM_CORE.HOSTS alter table CCM_CORE.HOSTS
add constraint UK9ramlv6uxwt13v0wj7q0tucsx unique (SERVER_NAME, SERVER_PORT); add constraint UK9ramlv6uxwt13v0wj7q0tucsx unique (SERVER_NAME, SERVER_PORT);

View File

@ -1,7 +1,9 @@
ccm_core.ccm_roles: ccm_core.ccm_roles:
- role_id: -10001 - role_id: -10001
uuid: 42038ba3-35b9-4894-843f-cb39ae1be763
name: role1 name: role1
- role_id: -10002 - role_id: -10002
uuid: c821a93d-78aa-4b87-ac1b-3e3229e0fdd9
name: role2 name: role2
ccm_core.ccm_objects: ccm_core.ccm_objects:
- object_id: -20001 - object_id: -20001

View File

@ -1,7 +1,9 @@
ccm_core.ccm_roles: ccm_core.ccm_roles:
- role_id: -10001 - role_id: -10001
uuid: 42038ba3-35b9-4894-843f-cb39ae1be763
name: role1 name: role1
- role_id: -10002 - role_id: -10002
uuid: c821a93d-78aa-4b87-ac1b-3e3229e0fdd9
name: role2 name: role2
ccm_core.ccm_objects: ccm_core.ccm_objects:
- object_id: -20001 - object_id: -20001

View File

@ -1,7 +1,9 @@
ccm_core.ccm_roles: ccm_core.ccm_roles:
- role_id: -10001 - role_id: -10001
uuid: 42038ba3-35b9-4894-843f-cb39ae1be763
name: role1 name: role1
- role_id: -10002 - role_id: -10002
uuid: c821a93d-78aa-4b87-ac1b-3e3229e0fdd9
name: role2 name: role2
ccm_core.ccm_objects: ccm_core.ccm_objects:
- object_id: -20001 - object_id: -20001

View File

@ -1,7 +1,9 @@
ccm_core.ccm_roles: ccm_core.ccm_roles:
- role_id: -10001 - role_id: -10001
uuid: 42038ba3-35b9-4894-843f-cb39ae1be763
name: role1 name: role1
- role_id: -10002 - role_id: -10002
uuid: c821a93d-78aa-4b87-ac1b-3e3229e0fdd9
name: role2 name: role2
ccm_core.ccm_objects: ccm_core.ccm_objects:
- object_id: -20001 - object_id: -20001

View File

@ -1,7 +1,9 @@
ccm_core.ccm_roles: ccm_core.ccm_roles:
- role_id: -10001 - role_id: -10001
uuid: 42038ba3-35b9-4894-843f-cb39ae1be763
name: role1 name: role1
- role_id: -10002 - role_id: -10002
uuid: c821a93d-78aa-4b87-ac1b-3e3229e0fdd9
name: role2 name: role2
ccm_core.ccm_objects: ccm_core.ccm_objects:
- object_id: -20001 - object_id: -20001

View File

@ -1,7 +1,9 @@
ccm_core.ccm_roles: ccm_core.ccm_roles:
- role_id: -10001 - role_id: -10001
uuid: 42038ba3-35b9-4894-843f-cb39ae1be763
name: role1 name: role1
- role_id: -10002 - role_id: -10002
uuid: c821a93d-78aa-4b87-ac1b-3e3229e0fdd9
name: role2 name: role2
ccm_core.ccm_objects: ccm_core.ccm_objects:
- object_id: -20001 - object_id: -20001

View File

@ -1,7 +1,9 @@
ccm_core.ccm_roles: ccm_core.ccm_roles:
- role_id: -10001 - role_id: -10001
uuid: 42038ba3-35b9-4894-843f-cb39ae1be763
name: role1 name: role1
- role_id: -10002 - role_id: -10002
uuid: c821a93d-78aa-4b87-ac1b-3e3229e0fdd9
name: role2 name: role2
ccm_core.ccm_objects: ccm_core.ccm_objects:
- object_id: -20001 - object_id: -20001

View File

@ -1,7 +1,9 @@
ccm_core.ccm_roles: ccm_core.ccm_roles:
- role_id: -10001 - role_id: -10001
uuid: 42038ba3-35b9-4894-843f-cb39ae1be763
name: role1 name: role1
- role_id: -10002 - role_id: -10002
uuid: c821a93d-78aa-4b87-ac1b-3e3229e0fdd9
name: role2 name: role2
ccm_core.ccm_objects: ccm_core.ccm_objects:
- object_id: -20001 - object_id: -20001

View File

@ -82,10 +82,13 @@ ccm_core.group_memberships:
member_id: -30 member_id: -30
ccm_core.ccm_roles: ccm_core.ccm_roles:
- role_id: -2000 - role_id: -2000
uuid: 42038ba3-35b9-4894-843f-cb39ae1be763
name: role1 name: role1
- role_id: -2100 - role_id: -2100
uuid: c821a93d-78aa-4b87-ac1b-3e3229e0fdd9
name: role2 name: role2
- role_id: -2200 - role_id: -2200
uuid: 0e73623c-8d6a-4544-88a4-e4b104e7c0b6
name: role3 name: role3
ccm_core.role_memberships: ccm_core.role_memberships:
# role1 <-> jdoe # role1 <-> jdoe

View File

@ -82,10 +82,13 @@ ccm_core.group_memberships:
member_id: -30 member_id: -30
ccm_core.ccm_roles: ccm_core.ccm_roles:
- role_id: -2000 - role_id: -2000
uuid: 42038ba3-35b9-4894-843f-cb39ae1be763
name: role1 name: role1
- role_id: -2100 - role_id: -2100
uuid: c821a93d-78aa-4b87-ac1b-3e3229e0fdd9
name: role2 name: role2
- role_id: -2200 - role_id: -2200
uuid: 0e73623c-8d6a-4544-88a4-e4b104e7c0b6
name: role3 name: role3
ccm_core.role_memberships: ccm_core.role_memberships:
# role1 <-> group3 # role1 <-> group3

View File

@ -82,10 +82,13 @@ ccm_core.group_memberships:
member_id: -30 member_id: -30
ccm_core.ccm_roles: ccm_core.ccm_roles:
- role_id: -2000 - role_id: -2000
uuid: 42038ba3-35b9-4894-843f-cb39ae1be763
name: role1 name: role1
- role_id: -2100 - role_id: -2100
uuid: c821a93d-78aa-4b87-ac1b-3e3229e0fdd9
name: role2 name: role2
- role_id: -2200 - role_id: -2200
uuid: 0e73623c-8d6a-4544-88a4-e4b104e7c0b6
name: role3 name: role3
ccm_core.role_memberships: ccm_core.role_memberships:
# role1 <-> jdoe # role1 <-> jdoe

View File

@ -1,5 +1,7 @@
ccm_core.ccm_roles: ccm_core.ccm_roles:
- role_id: -10 - role_id: -10
uuid: 42038ba3-35b9-4894-843f-cb39ae1be763
name: administrator name: administrator
- role_id: -30 - role_id: -30
uuid: 0e73623c-8d6a-4544-88a4-e4b104e7c0b6
name: reader name: reader

View File

@ -1,7 +1,10 @@
ccm_core.ccm_roles: ccm_core.ccm_roles:
- role_id: -10 - role_id: -10
uuid: 42038ba3-35b9-4894-843f-cb39ae1be763
name: administrator name: administrator
- role_id: -20 - role_id: -20
uuid: c821a93d-78aa-4b87-ac1b-3e3229e0fdd9
name: writer name: writer
- role_id: -30 - role_id: -30
uuid: 0e73623c-8d6a-4544-88a4-e4b104e7c0b6
name: reader name: reader

View File

@ -1,9 +1,13 @@
ccm_core.ccm_roles: ccm_core.ccm_roles:
- role_id: -10 - role_id: -10
uuid: 42038ba3-35b9-4894-843f-cb39ae1be763
name: administrator name: administrator
- role_id: -20 - role_id: -20
uuid: c821a93d-78aa-4b87-ac1b-3e3229e0fdd9
name: user name: user
- role_id: -30 - role_id: -30
uuid: 0e73623c-8d6a-4544-88a4-e4b104e7c0b6
name: reader name: reader
- role_id: -40 - role_id: -40
uuid: 9feb2623-671a-4fd4-bd3f-1adc7f51f62e
name: editor name: editor

View File

@ -1,7 +1,10 @@
ccm_core.ccm_roles: ccm_core.ccm_roles:
- role_id: -10 - role_id: -10
uuid: 42038ba3-35b9-4894-843f-cb39ae1be763
name: administrator name: administrator
- role_id: -20 - role_id: -20
uuid: c821a93d-78aa-4b87-ac1b-3e3229e0fdd9
name: user name: user
- role_id: -30 - role_id: -30
uuid: 0e73623c-8d6a-4544-88a4-e4b104e7c0b6
name: reader name: reader

View File

@ -98,10 +98,13 @@ ccm_core.group_memberships:
member_id: -41003 member_id: -41003
ccm_core.ccm_roles: ccm_core.ccm_roles:
- role_id: -10001 - role_id: -10001
uuid: 42038ba3-35b9-4894-843f-cb39ae1be763
name: role1 name: role1
- role_id: -10002 - role_id: -10002
uuid: c821a93d-78aa-4b87-ac1b-3e3229e0fdd9
name: role2 name: role2
- role_id: -10003 - role_id: -10003
uuid: 0e73623c-8d6a-4544-88a4-e4b104e7c0b6
name: public-role name: public-role
ccm_core.role_memberships: ccm_core.role_memberships:
# role1 <-> group1 # role1 <-> group1