Commit 2fcb9abe authored by Aleh Shubko [EPAM]'s avatar Aleh Shubko [EPAM]
Browse files

Update context cofiguration

parent cdb385bc
......@@ -33,4 +33,7 @@ target/
#Intellij
.idea
*.iml
*/*.iml
\ No newline at end of file
*/*.iml
# in-memory mongo runtime files
mongocryptd.pid
\ No newline at end of file
......@@ -5,22 +5,33 @@ A MongoDB implementation of basic functionality for OSDU applications. The libra
List of services supported:
* Storage
* Legal
* [In progress] Entitlements
* [...TBD...]
# How to import into service
- Import this artifact to your application's `pom.xml`:
- Import required application artifact to your application's `pom.xml`:
```
<dependency>
<groupId>org.opengroup.osdu.core.mongodb</groupId>
<artifactId>os-core-lib-mongodb</artifactId>
<version>0.1.1</version>
<artifactId>storage</artifactId>
<version>0.1.8</version>
</dependency>
<!-- or -->
<dependency>
<groupId>org.opengroup.osdu.core.mongodb</groupId>
<artifactId>legal</artifactId>
<version>0.1.8</version>
</dependency>
<!-- or -->
<dependency>
<groupId>org.opengroup.osdu.core.mongodb</groupId>
<artifactId>entitlements</artifactId>
<version>0.1.8</version>
</dependency>
```
- Add following to your `application.properties` file:
```
osdu.mongodb.enabled.storage=true # to enable storage helpers
osdu.mongodb.enabled.legal=true # to enable legal helpers
osdu.mongodb.database=[your_database_name]
osdu.mongodb.uri=[connection url to MongoDB Atlas cluster or any MongoDB instance/replica (no matter on-premice or cloud)]
```
......@@ -40,4 +51,9 @@ All the beans for now have all the necessary methods to implement the correspond
There is `LegalHelper` for `ILegalTagRepository`.
### Entitlements application
For all the SPI's in 'org.opengroup.osdu.entitlements.v2.spi' there is a corresponding helper implementation.
To configure the module you must include `osdu.mongodb.domain` into your `application.properties` config.
#### [...TBD...]
\ No newline at end of file
......@@ -7,7 +7,7 @@
<parent>
<groupId>org.opengroup.osdu.core.mongodb</groupId>
<artifactId>os-core-lib-mongodb</artifactId>
<version>0.1.6</version>
<version>0.1.8</version>
</parent>
<artifactId>entitlements</artifactId>
......@@ -45,4 +45,4 @@
</plugins>
</build>
</project>
\ No newline at end of file
</project>
package org.opengroup.osdu.core.common.logging;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Strings;
import lombok.SneakyThrows;
import org.opengroup.osdu.core.common.logging.audit.AuditAction;
import org.opengroup.osdu.core.common.logging.audit.AuditPayload;
import org.opengroup.osdu.core.common.logging.audit.AuditStatus;
import org.opengroup.osdu.core.common.model.Role;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static java.util.Collections.singletonList;
class AuditEvents {
private static final String REDIS_BACKUP_ACTION_ID = "ET201";
private static final String REDIS_BACKUP_MESSAGE = "Back up redis instance";
private static final String REDIS_LIST_BACKUP_VERSIONS_ACTION_ID = "ET202";
private static final String REDIS_LIST_BACKUP_VERSIONS_MESSAGE = "List backup version of the redis instance";
private static final String REDIS_RESTORE_ACTION_ID = "ET203";
private static final String REDIS_RESTORE_MESSAGE = "Restore redis instance from version %s";
private static final String REDIS_CREATE_GROUP_TRANSACTION_ACTION_ID = "ET210";
private static final String REDIS_CREATE_GROUP_TRANSACTION_MESSAGE = "Create group %s";
private static final String REDIS_DELETE_GROUP_TRANSACTION_ACTION_ID = "ET211";
private static final String REDIS_DELETE_GROUP_TRANSACTION_MESSAGE = "Delete group %s";
private static final String REDIS_LIST_GROUP_TRANSACTION_ACTION_ID = "ET212";
private static final String REDIS_LIST_GROUP_TRANSACTION_MESSAGE = "Return all groups the caller belongs to of the tenant";
private static final String REDIS_ADD_MEMBER_TRANSACTION_ACTION_ID = "ET213";
private static final String REDIS_ADD_MEMBER_TRANSACTION_MESSAGE = "Add entity %s to group %s as %s";
private static final String REDIS_REMOVE_MEMBER_TRANSACTION_ACTION_ID = "ET214";
private static final String REDIS_REMOVE_MEMBER_TRANSACTION_MESSAGE = "Remove entity %s to group %s as requested by %s";
private static final String REDIS_LIST_MEMBER_TRANSACTION_ACTION_ID = "ET215";
private static final String REDIS_LIST_MEMBER_TRANSACTION_MESSAGE = "Return all direct members of group %s";
private static final String REDIS_UPDATE_APP_IDS_TRANSACTION_ACTION_ID = "ET216";
private static final String REDIS_UPDATE_APP_IDS_TRANSACTION_MESSAGE = "Update appId for group %s to %s";
private static final String REDIS_UPDATE_GROUP_TRANSACTION_ACTION_ID = "ET217";
private static final String REDIS_UPDATE_GROUP_TRANSACTION_MESSAGE = "Update group %s";
private static final String REDIS_UPDATE_GROUPS_IN_CACHE_FOR_KEYS_ACTION_ID = "ET219";
private static final String REDIS_UPDATE_GROUPS_IN_CACHE_FOR_KEYS_MESSAGE = "Update groups in cache for given keys";
private final String user;
private final String dataPartitionId;
private ObjectMapper mapper = new ObjectMapper();
AuditEvents(String user, String dataPartitionId) {
if (Strings.isNullOrEmpty(user)) {
throw new IllegalArgumentException("User not supplied for audit events");
}
this.user = user;
this.dataPartitionId = dataPartitionId;
}
AuditPayload getRedisBackupEvent(AuditStatus auditStatus) {
return AuditPayload.builder()
.action(AuditAction.JOB_RUN)
.status(auditStatus)
.user(this.user)
.actionId(REDIS_BACKUP_ACTION_ID)
.message(REDIS_BACKUP_MESSAGE)
.resources(singletonList(dataPartitionId))
.build();
}
AuditPayload getRedisBackupVersionEvent(AuditStatus auditStatus) {
return AuditPayload.builder()
.action(AuditAction.READ)
.status(auditStatus)
.user(this.user)
.actionId(REDIS_LIST_BACKUP_VERSIONS_ACTION_ID)
.message(REDIS_LIST_BACKUP_VERSIONS_MESSAGE)
.resources(singletonList(dataPartitionId))
.build();
}
AuditPayload getRedisRestoreEvent(AuditStatus auditStatus, String version) {
return AuditPayload.builder()
.action(AuditAction.UPDATE)
.status(auditStatus)
.user(this.user)
.actionId(REDIS_RESTORE_ACTION_ID)
.message(String.format(REDIS_RESTORE_MESSAGE, version))
.resources(singletonList(dataPartitionId))
.build();
}
AuditPayload getCreateGroupEvent(AuditStatus auditStatus, String groupId) {
return AuditPayload.builder()
.action(AuditAction.CREATE)
.status(auditStatus)
.user(this.user)
.actionId(REDIS_CREATE_GROUP_TRANSACTION_ACTION_ID)
.message(String.format(REDIS_CREATE_GROUP_TRANSACTION_MESSAGE, groupId))
.resources(Arrays.asList(dataPartitionId, groupId))
.build();
}
AuditPayload getUpdateGroupEvent(AuditStatus auditStatus, String groupId) {
return AuditPayload.builder()
.action(AuditAction.UPDATE)
.status(auditStatus)
.user(this.user)
.actionId(REDIS_UPDATE_GROUP_TRANSACTION_ACTION_ID)
.message(String.format(REDIS_UPDATE_GROUP_TRANSACTION_MESSAGE, groupId))
.resources(Arrays.asList(dataPartitionId, groupId))
.build();
}
AuditPayload getDeleteGroupEvent(AuditStatus auditStatus, String groupId) {
return AuditPayload.builder()
.action(AuditAction.DELETE)
.status(auditStatus)
.user(this.user)
.actionId(REDIS_DELETE_GROUP_TRANSACTION_ACTION_ID)
.message(String.format(REDIS_DELETE_GROUP_TRANSACTION_MESSAGE, groupId))
.resources(Arrays.asList(dataPartitionId, groupId))
.build();
}
AuditPayload getAddMemberEvent(AuditStatus auditStatus, String groupId, String memberId, Role role) {
return AuditPayload.builder()
.action(AuditAction.UPDATE)
.status(auditStatus)
.user(this.user)
.actionId(REDIS_ADD_MEMBER_TRANSACTION_ACTION_ID)
.message(String.format(REDIS_ADD_MEMBER_TRANSACTION_MESSAGE, memberId, groupId, role))
.resources(Arrays.asList(dataPartitionId, groupId, memberId, role.toString()))
.build();
}
AuditPayload getRemoveMemberEvent(AuditStatus auditStatus, String groupId, String memberId, String requesterId) {
return AuditPayload.builder()
.action(AuditAction.DELETE)
.status(auditStatus)
.user(this.user)
.actionId(REDIS_REMOVE_MEMBER_TRANSACTION_ACTION_ID)
.message(String.format(REDIS_REMOVE_MEMBER_TRANSACTION_MESSAGE, memberId, groupId, requesterId))
.resources(Arrays.asList(dataPartitionId, groupId, memberId, requesterId))
.build();
}
AuditPayload getListGroupEvent(AuditStatus auditStatus, List<String> groupIds) {
return AuditPayload.builder()
.action(AuditAction.READ)
.status(auditStatus)
.user(this.user)
.actionId(REDIS_LIST_GROUP_TRANSACTION_ACTION_ID)
.message(REDIS_LIST_GROUP_TRANSACTION_MESSAGE)
.resources(Stream.concat(Collections.singletonList(dataPartitionId).stream(), groupIds.stream()).collect(Collectors.toList()))
.build();
}
AuditPayload getListMemberEvent(AuditStatus auditStatus, String groupId) {
return AuditPayload.builder()
.action(AuditAction.READ)
.status(auditStatus)
.user(this.user)
.actionId(REDIS_LIST_MEMBER_TRANSACTION_ACTION_ID)
.message(String.format(REDIS_LIST_MEMBER_TRANSACTION_MESSAGE, groupId))
.resources(Arrays.asList(dataPartitionId, groupId))
.build();
}
@SneakyThrows
AuditPayload getUpdateAppIdsEvent(AuditStatus auditStatus, String groupId, Set<String> appIds) {
return AuditPayload.builder()
.action(AuditAction.UPDATE)
.status(auditStatus)
.user(this.user)
.actionId(REDIS_UPDATE_APP_IDS_TRANSACTION_ACTION_ID)
.message(String.format(REDIS_UPDATE_APP_IDS_TRANSACTION_MESSAGE, groupId, mapper.writeValueAsString(appIds)))
.resources(Arrays.asList(dataPartitionId, groupId))
.build();
}
AuditPayload getUpdateGroupsInCacheForKeysEvent(AuditStatus auditStatus, Set<String> keys) {
return AuditPayload.builder()
.action(AuditAction.UPDATE)
.status(auditStatus)
.user(user)
.actionId(REDIS_UPDATE_GROUPS_IN_CACHE_FOR_KEYS_ACTION_ID)
.message(REDIS_UPDATE_GROUPS_IN_CACHE_FOR_KEYS_MESSAGE)
.resources(new ArrayList<>(keys))
.build();
}
}
package org.opengroup.osdu.core.common.logging;
import org.opengroup.osdu.core.common.logging.audit.AuditPayload;
import org.opengroup.osdu.core.common.logging.audit.AuditStatus;
import org.opengroup.osdu.core.common.model.Role;
import org.opengroup.osdu.core.common.model.http.DpsHeaders;
import org.opengroup.osdu.core.common.model.http.RequestInfo;
import org.springframework.stereotype.Component;
import org.springframework.web.context.annotation.RequestScope;
import java.util.List;
import java.util.Set;
/**
* DO NOT USE THIS
* BEHAVIOUR IS MOCKED FOR TESTS
*/
@Component
@RequestScope
public class AuditLogger {
private JaxRsDpsLog logger;
private RequestInfo requestInfo;
private AuditEvents events = null;
private AuditEvents getEvents() {
if (this.events == null) {
DpsHeaders headers = this.requestInfo.getHeaders();
String userId = "unit-test-id";
this.events = new AuditEvents(userId, headers.getPartitionId());
}
return this.events;
}
public void redisInstanceBackup(AuditStatus auditStatus) {
this.writeLog(this.getEvents().getRedisBackupEvent(auditStatus));
}
public void redisInstanceBackupVersions(AuditStatus auditStatus) {
this.writeLog(this.getEvents().getRedisBackupVersionEvent(auditStatus));
}
public void redisInstanceRestore(AuditStatus auditStatus, String version) {
this.writeLog(this.getEvents().getRedisRestoreEvent(auditStatus, version));
}
public void createGroup(AuditStatus auditStatus, String groupId) {
this.writeLog(this.getEvents().getCreateGroupEvent(auditStatus, groupId));
}
public void updateGroup(AuditStatus auditStatus, String groupId) {
this.writeLog(this.getEvents().getUpdateGroupEvent(auditStatus, groupId));
}
public void deleteGroup(AuditStatus auditStatus, String groupId) {
this.writeLog(this.getEvents().getDeleteGroupEvent(auditStatus, groupId));
}
public void addMember(AuditStatus auditStatus, String groupId, String memberId, Role role) {
this.writeLog(this.getEvents().getAddMemberEvent(auditStatus, groupId, memberId, role));
}
public void removeMember(AuditStatus auditStatus, String groupId, String memberId, String requesterId) {
this.writeLog(this.getEvents().getRemoveMemberEvent(auditStatus, groupId, memberId, requesterId));
}
public void listGroup(AuditStatus auditStatus, List<String> groupIds) {
this.writeLog(this.getEvents().getListGroupEvent(auditStatus, groupIds));
}
public void listMember(AuditStatus auditStatus, String groupId) {
this.writeLog(this.getEvents().getListMemberEvent(auditStatus, groupId));
}
public void updateAppIds(AuditStatus auditStatus, String groupId, Set<String> appIds) {
this.writeLog(this.getEvents().getUpdateAppIdsEvent(auditStatus, groupId, appIds));
}
public void updateGroupsInCacheForKeys(AuditStatus auditStatus, Set<String> keys) {
this.writeLog(this.getEvents().getUpdateGroupsInCacheForKeysEvent(auditStatus, keys));
}
private void writeLog(AuditPayload log) {
this.logger.audit(log);
}
}
package org.opengroup.osdu.core.common.logging;
import lombok.RequiredArgsConstructor;
import org.opengroup.osdu.core.common.http.ResponseHeaders;
import org.opengroup.osdu.core.common.model.http.DpsHeaders;
import org.opengroup.osdu.core.common.model.http.Request;
import org.opengroup.osdu.core.common.model.http.RequestInfo;
import org.springframework.stereotype.Component;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.Duration;
import java.util.List;
import java.util.Map;
@Component
@RequiredArgsConstructor
public class ResponseLogFilter implements Filter {
private final RequestInfo requestInfo;
private final JaxRsDpsLog logger;
@Override
public void init(FilterConfig filterConfig) {
//do nothing
}
@Override
public void doFilter(ServletRequest servletRequest,
ServletResponse servletResponse,
FilterChain filterChain) throws IOException, ServletException {
String uri = requestInfo.getUri();
if (isNotHealthCheckRequest(uri)) {
logger.info(String.format("ResponseLogFilter#doFilter start timestamp: %d", System.currentTimeMillis()));
}
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;
requestInfo.getHeaders().addCorrelationIdIfMissing();
setResponseHeaders(httpServletResponse);
long startTime;
Object property = httpServletRequest.getServletContext().getAttribute("starttime");
if (property == null) {
startTime = System.currentTimeMillis();
} else {
startTime = (long) property;
}
try {
if (isOptionsRequest(httpServletRequest)) {
httpServletResponse.setStatus(200);
} else {
filterChain.doFilter(servletRequest, servletResponse);
}
} finally {
if (isNotHealthCheckRequest(uri)) {
logRequest(uri, httpServletRequest, httpServletResponse, startTime);
logger.info(String.format("ResponseLogFilter#doFilter done timestamp: %d", System.currentTimeMillis()));
}
}
}
private void setResponseHeaders(HttpServletResponse httpServletResponse) {
for (Map.Entry<String, List<Object>> header : ResponseHeaders.STANDARD_RESPONSE_HEADERS.entrySet()) {
StringBuilder builder = new StringBuilder();
header.getValue().forEach(builder::append);
httpServletResponse.addHeader(header.getKey(), builder.toString());
}
httpServletResponse.addHeader(DpsHeaders.CORRELATION_ID, requestInfo.getHeaders().getCorrelationId());
}
private boolean isNotHealthCheckRequest(String uri) {
return (!uri.endsWith("/liveness_check") && !uri.endsWith("/readiness_check"));
}
private boolean isOptionsRequest(HttpServletRequest request) {
return request.getMethod().equalsIgnoreCase("OPTIONS");
}
private void logRequest(String uri, HttpServletRequest request, HttpServletResponse response, long startTime) {
logger.request(Request.builder()
.requestMethod(request.getMethod())
.latency(Duration.ofMillis(System.currentTimeMillis() - startTime))
.requestUrl(uri)
.Status(response.getStatus())
.ip(requestInfo.getUserIp())
.build());
}
}
package org.opengroup.osdu.core.common.model;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.Generated;
import lombok.NoArgsConstructor;
@Data
@Generated
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class ChildrenReference {
private String id;
private String dataPartitionId;
private NodeType type;
private Role role;
public Role getRole() {
return role;
}
public String getId() {
return id;
}
public String getDataPartitionId() {
return dataPartitionId;
}
public NodeType getType() {
return type;
}
public static ChildrenReference createChildrenReference(EntityNode memberNode, Role role) {
return ChildrenReference.builder()
.id(memberNode.getNodeId())
.type(memberNode.getType())
.role(role)
.dataPartitionId(memberNode.getDataPartitionId())
.build();
}
public boolean isGroup() {
return type == NodeType.GROUP;
}
public boolean isUser() {
return type == NodeType.USER;
}
public boolean isOwner() {
return role == Role.OWNER;
}
public boolean isUsersDataRootGroup() {
return id.startsWith("users.data.root@");
}
}
package org.opengroup.osdu.core.common.model;
import com.dslplatform.json.JsonAttribute;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.Generated;
import lombok.NoArgsConstructor;
import org.opengroup.osdu.core.common.spi.retrievegroup.RetrieveGroupRepo;
import org.opengroup.osdu.core.common.util.JsonConverter;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
@Data
@Generated
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class EntityNode {
private String nodeId;
private NodeType type;
private String name;
@Builder.Default
private String description = "";
private String dataPartitionId;
@Builder.Default
private Set<String> appIds = new HashSet<>();
public static EntityNodeBuilder builder() {
return new EntityNodeBuilder();
}
public static final int MAX_PARENTS = 5000;
public static final String ROOT_DATA_GROUP_EMAIL_FORMAT = "users.data.root@%s";
@JsonIgnore
public String getUniqueIdentifier() {
return String.format("%s-%s", nodeId, dataPartitionId);
}
@JsonAttribute(index = 4)
public String getNodeId() {
return nodeId;
}
@JsonAttribute(index = 5)
public NodeType getType() {