Skip to content
Open
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
1 change: 0 additions & 1 deletion .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

51 changes: 46 additions & 5 deletions .idea/workspace.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions src/main/java/upr/famnit/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import upr.famnit.util.Config;
import upr.famnit.util.Logger;

import javax.xml.crypto.Data;
import java.io.*;
import java.sql.SQLException;

Expand All @@ -16,6 +17,9 @@ public static void main(String[] args) {
try {
Config.init();
DatabaseManager.createKeysTable();
DatabaseManager.createBlockedModelsTable();
DatabaseManager.createWhiteListTable();
DatabaseManager.createExclusiveModelsTable();

WorkerServer workerServer = new WorkerServer();
ClientServer clientServer = new ClientServer();
Expand Down
23 changes: 23 additions & 0 deletions src/main/java/upr/famnit/authentication/AllowedModelsTable.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package upr.famnit.authentication;

import upr.famnit.components.NodeData;
import upr.famnit.components.WorkerVersion;
import upr.famnit.managers.connections.Worker;

import java.util.ArrayList;
import java.util.List;

public class AllowedModelsTable {
private Key key;
private ArrayList<String>tagsAllowed;

public void SetKey(Key kateri){
this.key=kateri;
}
public Key getKey(Key kateri){
return key;
}
public void getArr(){

}
}
18 changes: 18 additions & 0 deletions src/main/java/upr/famnit/authentication/Role.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
* <li>{@code Client}: Represents a standard client with limited access rights.</li>
* <li>{@code Worker}: Represents a worker entity with elevated permissions.</li>
* <li>{@code Admin}: Represents an administrator with full access rights.</li>
* <li>{@code Researcher}: Represents an administrator with full access rights.</li>
* <li>{@code Unknown}: Represents an undefined or unrecognized role.</li>
* </ul>
* </p>
Expand All @@ -35,6 +36,11 @@ public enum Role {
*/
Admin,

/**
* Represents a researcher with lower priority queing
*/
Researcher,

/**
* Represents an undefined or unrecognized role.
*/
Expand All @@ -60,9 +66,21 @@ public String toString() {
case Admin -> {
return "Admin";
}
case Researcher ->{
return "Researcher";
}
default -> {
return "Unknown";
}
}
}
public static Role fromString(String a) {
if (a == null) return null;
try {
return Role.valueOf(a.trim());
} catch (IllegalArgumentException e) {
return null; // unknown string
}
}

}
3 changes: 3 additions & 0 deletions src/main/java/upr/famnit/authentication/RoleUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ public static Role fromString(String role) {
case "admin" -> {
return Role.Admin;
}
case "researcher"->{
return Role.Researcher;
}
default -> {
return Role.Unknown;
}
Expand Down
11 changes: 11 additions & 0 deletions src/main/java/upr/famnit/components/Request.java
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,17 @@ public byte[] getBody() {
return body != null ? body.clone() : null;
}

/**
* Retrieves the head of the request.
*
* @return the request head as a String, or {@code null} if no head is present
*/
public String getHeader(String name) {
if (name == null) return null;
return headers.get(name.toLowerCase());
}


/**
* Logs the details of the request using the {@link Logger}.
*
Expand Down
97 changes: 95 additions & 2 deletions src/main/java/upr/famnit/components/RequestQue.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
package upr.famnit.components;

import upr.famnit.managers.DatabaseManager;
import upr.famnit.util.LogLevel;
import upr.famnit.util.Logger;
import upr.famnit.util.StreamUtil;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
Expand Down Expand Up @@ -94,11 +98,16 @@ public static ClientRequest getModelTask(String modelName, String nodeName) {
* @param request the {@link ClientRequest} to be added
* @return {@code true} if the task was successfully added; {@code false} otherwise
*/
public static boolean addTask(ClientRequest request) {
public static boolean addTask(ClientRequest request) throws SQLException {
if (request.getRequest().getProtocol().equals("HIVE")) {
return false;
}

String model = extractModel(request);
String token = extractToken(request);
if(!isAllowedForModel(model,token)){
Logger.log("Model not allowed for the person", LogLevel.error);
return false;
}
if (request.getRequest().getHeaders().containsKey("node")) {
return addToQueByNode(request);
} else {
Expand Down Expand Up @@ -236,5 +245,89 @@ public static ClientRequest getUnhandlableTask(ArrayList<String> nodeNames, Set<

return null;
}
/**
* Extracts the model name from the JSON request body.
*
* <p>This expects the request body to contain a JSON key named {@code "model"}.
* If the key is missing or unreadable, {@code null} is returned.</p>
*
* @param request the {@link ClientRequest} whose model should be extracted
* @return the model name, or {@code null} if not found
*/
public static String extractModel(ClientRequest request) {
return StreamUtil.getValueFromJSONBody("model", request.getRequest().getBody());
}

/**
* Extracts a Bearer token from the request's {@code Authorization} header.
*
* <p>The header must be in the format:</p>
* <pre>
* Authorization: Bearer &lt;token&gt;
* </pre>
*
* <p>If the header is missing, malformed, or does not begin with "Bearer ",
* {@code null} is returned.</p>
*
* @param request the {@link ClientRequest} containing the Authorization header
* @return the extracted token, or {@code null} if not present or invalid
*/
public static String extractToken(ClientRequest request) {
String auth = request.getRequest().getHeaders().get("Authorization");
if (auth == null) return null;
if (!auth.startsWith("Bearer ")) return null;
return auth.substring("Bearer ".length()).trim();
}

/**
* Determines whether a given key is allowed to access a specific model.
*
* <p><b>Permission rules (evaluated in order of precedence):</b></p>
*
* <ol>
* <li><b>Global exclusivity (strongest rule):</b><br>
* If the model is exclusive to a different key, access is denied.
* If the model is not exclusive or is exclusive to this key, evaluation continues.</li>
*
* <li><b>Block list (hard deny):</b><br>
* If the model appears in the key's block list, access is denied.</li>
*
* <li><b>Allow list (conditional whitelist):</b><br>
* If the allow list is non-empty, the model must be present in it.
* If the allow list is empty, all non-blocked models are permitted.</li>
* </ol>
*
* <p>This method retrieves exclusivity, allow-list, and block-list data
* from the database on each invocation.</p>
*
* @param keyValue the key requesting access to the model
* @param modelName the model being requested
*
* @return {@code true} if access is permitted; {@code false} otherwise
*
* @throws SQLException if permission or exclusivity data cannot be retrieved
*/
public static synchronized boolean isAllowedForModel(String keyValue, String modelName ) throws SQLException {
//Vičič special
String exclusiveOwner = DatabaseManager.getExclusiveOwnerForModel(modelName);
if (exclusiveOwner != null && !exclusiveOwner.equals(keyValue)) {
Logger.warn("Model '" + modelName + "' is exclusive to another key.");
return false;
}
//Black list
if (DatabaseManager.getBlockedModelsForKey(keyValue).contains(modelName)) {
Logger.info("Model '" + modelName + "' is blocked for key " + keyValue);
return false;
}

//White list
ArrayList<String> allow = DatabaseManager.getAllowedModelsForKey(keyValue);
if (!allow.isEmpty() && !allow.contains(modelName)) {
Logger.info("Model '" + modelName + "' not in allow list for key " + keyValue);
return false;
}

return true;
}

}
Loading