Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 98 additions & 0 deletions api/src/main/java/org/apache/unomi/api/ExecutionContext.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.unomi.api;

import java.util.HashSet;
import java.util.Set;
import java.util.Stack;

/**
* Represents the execution context for operations in Unomi, including security and tenant information.
*/
public class ExecutionContext {
public static final String SYSTEM_TENANT = "system";

private String tenantId;
private Set<String> roles = new HashSet<>();
private Set<String> permissions = new HashSet<>();
private Stack<String> tenantStack = new Stack<>();
private boolean isSystem = false;

public ExecutionContext(String tenantId, Set<String> roles, Set<String> permissions) {
this.tenantId = tenantId;
if (tenantId != null && tenantId.equals(SYSTEM_TENANT)) {
this.isSystem = true;
}
if (roles != null) {
this.roles.addAll(roles);
}
if (permissions != null) {
this.permissions.addAll(permissions);
}
}

public static ExecutionContext systemContext() {
ExecutionContext context = new ExecutionContext(SYSTEM_TENANT, null, null);
context.isSystem = true;
return context;
}

public String getTenantId() {
return tenantId;
}

public Set<String> getRoles() {
return new HashSet<>(roles);
}

public Set<String> getPermissions() {
return new HashSet<>(permissions);
}

public boolean isSystem() {
return isSystem;
}

public void setTenant(String tenantId) {
tenantStack.push(this.tenantId);
this.tenantId = tenantId;
}

public void restorePreviousTenant() {
if (!tenantStack.isEmpty()) {
this.tenantId = tenantStack.pop();
}
}

public void validateAccess(String operation) {
if (isSystem) {
return;
}

if (!hasPermission(operation)) {
throw new SecurityException("Access denied: Missing permission for operation " + operation + " for tenant " + tenantId + " and roles " + roles);
}
}

public boolean hasPermission(String permission) {
return isSystem || permissions.contains(permission);
}

public boolean hasRole(String role) {
return isSystem || roles.contains(role);
}
}
66 changes: 66 additions & 0 deletions api/src/main/java/org/apache/unomi/api/Item.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.slf4j.LoggerFactory;

import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
Expand Down Expand Up @@ -66,18 +67,32 @@ public static String getItemType(Class clazz) {
protected Long version;
protected Map<String, Object> systemMetadata = new HashMap<>();

// Audit metadata fields
private String createdBy;
private String lastModifiedBy;
private Date creationDate;
private Date lastModificationDate;
private String sourceInstanceId;
private Date lastSyncDate;

public Item() {
this.itemType = getItemType(this.getClass());
if (itemType == null) {
LOGGER.error("Item implementations must provide a public String constant named ITEM_TYPE to uniquely identify this Item for the persistence service.");
}
initializeAuditMetadata();
}

public Item(String itemId) {
this();
this.itemId = itemId;
}

private void initializeAuditMetadata() {
this.creationDate = new Date();
this.lastModificationDate = this.creationDate;
this.version = 0L;
}

/**
* Retrieves the Item's identifier used to uniquely identify this Item when persisted or when referred to. An Item's identifier must be unique among Items with the same type.
Expand Down Expand Up @@ -150,4 +165,55 @@ public Object getSystemMetadata(String key) {
public void setSystemMetadata(String key, Object value) {
systemMetadata.put(key, value);
}

// Audit metadata getters and setters
public String getCreatedBy() {
return createdBy;
}

public void setCreatedBy(String createdBy) {
this.createdBy = createdBy;
}

public String getLastModifiedBy() {
return lastModifiedBy;
}

public void setLastModifiedBy(String lastModifiedBy) {
this.lastModifiedBy = lastModifiedBy;
this.lastModificationDate = new Date();
this.version++;
}

public Date getCreationDate() {
return creationDate;
}

public void setCreationDate(Date creationDate) {
this.creationDate = creationDate;
}

public Date getLastModificationDate() {
return lastModificationDate;
}

public void setLastModificationDate(Date lastModificationDate) {
this.lastModificationDate = lastModificationDate;
}

public String getSourceInstanceId() {
return sourceInstanceId;
}

public void setSourceInstanceId(String sourceInstanceId) {
this.sourceInstanceId = sourceInstanceId;
}

public Date getLastSyncDate() {
return lastSyncDate;
}

public void setLastSyncDate(Date lastSyncDate) {
this.lastSyncDate = lastSyncDate;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.unomi.api.services;

import org.apache.unomi.api.ExecutionContext;

import java.util.function.Supplier;

/**
* Service interface for managing execution contexts in Unomi.
*/
public interface ExecutionContextManager {

/**
* Gets the current execution context.
* @return the current execution context
*/
ExecutionContext getCurrentContext();

/**
* Sets the current execution context.
* @param context the context to set as current
*/
void setCurrentContext(ExecutionContext context);

/**
* Executes an operation as the system user.
* @param operation the operation to execute
* @param <T> the return type of the operation
* @return the result of the operation
*/
<T> T executeAsSystem(Supplier<T> operation);

/**
* Executes an operation as the system user without return value.
* @param operation the operation to execute
*/
void executeAsSystem(Runnable operation);

/**
* Executes an operation as a specific tenant.
* This method creates a tenant context, executes the operation, and ensures proper cleanup.
* @param tenantId the ID of the tenant to execute as
* @param operation the operation to execute
* @param <T> the return type of the operation
* @return the result of the operation
*/
<T> T executeAsTenant(String tenantId, Supplier<T> operation);

/**
* Executes an operation as a specific tenant without return value.
* This method creates a tenant context, executes the operation, and ensures proper cleanup.
* @param tenantId the ID of the tenant to execute as
* @param operation the operation to execute
*/
void executeAsTenant(String tenantId, Runnable operation);

/**
* Creates a new execution context for the given tenant.
* @param tenantId the tenant ID
* @return the created execution context
*/
ExecutionContext createContext(String tenantId);
}
Loading
Loading