mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 13:17:41 +00:00
GUACAMOLE-462: Allow logs associated with history entries to be retrieved via REST.
This commit is contained in:
@@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* 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.guacamole.rest.history;
|
||||||
|
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
import javax.ws.rs.core.Response.ResponseBuilder;
|
||||||
|
import org.apache.guacamole.GuacamoleException;
|
||||||
|
import org.apache.guacamole.net.auth.ActivityLog;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A REST resource which exposes the contents of a given ActivityLog.
|
||||||
|
*/
|
||||||
|
public class ActivityLogResource {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ActivityLog whose contents are being exposed.
|
||||||
|
*/
|
||||||
|
private final ActivityLog log;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new ActivityLogResource which exposes the records within the
|
||||||
|
* given ActivityLog.
|
||||||
|
*
|
||||||
|
* @param log
|
||||||
|
* The ActivityLog whose contents should be exposed.
|
||||||
|
*/
|
||||||
|
public ActivityLogResource(ActivityLog log) {
|
||||||
|
this.log = log;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the raw contents of the underlying ActivityLog. If the size of
|
||||||
|
* the ActivityLog is known, this size is included as the "Content-Length"
|
||||||
|
* of the response.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A Response containing the raw contents of the underlying
|
||||||
|
* ActivityLog.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If an error prevents retrieving the content of the log or its size.
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
public Response getContents() throws GuacamoleException {
|
||||||
|
|
||||||
|
// Build base response exposing the raw contents of the underlying log
|
||||||
|
ResponseBuilder response = Response.ok(log.getContent(),
|
||||||
|
log.getType().getContentType());
|
||||||
|
|
||||||
|
// Include size, if known
|
||||||
|
long size = log.getSize();
|
||||||
|
if (size >= 0)
|
||||||
|
response.header("Content-Length", size);
|
||||||
|
|
||||||
|
return response.build();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* 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.guacamole.rest.history;
|
||||||
|
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.PathParam;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
import org.apache.guacamole.GuacamoleException;
|
||||||
|
import org.apache.guacamole.GuacamoleResourceNotFoundException;
|
||||||
|
import org.apache.guacamole.net.auth.ActivityLog;
|
||||||
|
import org.apache.guacamole.net.auth.ActivityRecord;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A REST resource which exposes a single ActivityRecord, allowing any
|
||||||
|
* associated and accessible logs to be retrieved.
|
||||||
|
*/
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
public class ActivityRecordResource {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ActivityRecord being exposed.
|
||||||
|
*/
|
||||||
|
private final ActivityRecord record;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new ActivityRecordResource which exposes the given record.
|
||||||
|
*
|
||||||
|
* @param record
|
||||||
|
* The ActivityRecord that should be exposed.
|
||||||
|
*/
|
||||||
|
public ActivityRecordResource(ActivityRecord record) {
|
||||||
|
this.record = record;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an ActivityLogResource representing the log associated with the
|
||||||
|
* underlying ActivityRecord and having the given name. If no such log
|
||||||
|
* can be retrieved, either because it does not exist or the current user
|
||||||
|
* does not have access, an exception is thrown.
|
||||||
|
*
|
||||||
|
* @param logName
|
||||||
|
* The unique name of the log to retrieve.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* An ActivityLogResource representing the log having the given name.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If no such log can be retrieved.
|
||||||
|
*/
|
||||||
|
@Path("logs/{name}")
|
||||||
|
public ActivityLogResource getLog(@PathParam("name") String logName)
|
||||||
|
throws GuacamoleException {
|
||||||
|
|
||||||
|
ActivityLog log = record.getLogs().get(logName);
|
||||||
|
if (log != null)
|
||||||
|
return new ActivityLogResource(log);
|
||||||
|
|
||||||
|
throw new GuacamoleResourceNotFoundException("No such log.");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -21,12 +21,17 @@ package org.apache.guacamole.rest.history;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
import javax.ws.rs.Consumes;
|
import javax.ws.rs.Consumes;
|
||||||
import javax.ws.rs.GET;
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.PathParam;
|
||||||
import javax.ws.rs.Produces;
|
import javax.ws.rs.Produces;
|
||||||
import javax.ws.rs.QueryParam;
|
import javax.ws.rs.QueryParam;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
|
import org.apache.guacamole.GuacamoleClientException;
|
||||||
import org.apache.guacamole.GuacamoleException;
|
import org.apache.guacamole.GuacamoleException;
|
||||||
|
import org.apache.guacamole.GuacamoleResourceNotFoundException;
|
||||||
import org.apache.guacamole.net.auth.ActivityRecord;
|
import org.apache.guacamole.net.auth.ActivityRecord;
|
||||||
import org.apache.guacamole.net.auth.ActivityRecordSet;
|
import org.apache.guacamole.net.auth.ActivityRecordSet;
|
||||||
|
|
||||||
@@ -86,6 +91,45 @@ public abstract class ActivityRecordSetResource<InternalRecordType extends Activ
|
|||||||
*/
|
*/
|
||||||
protected abstract ExternalRecordType toExternalRecord(InternalRecordType record);
|
protected abstract ExternalRecordType toExternalRecord(InternalRecordType record);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies the given search and sorting criteria to the ActivityRecordSet
|
||||||
|
* exposed by this ActivityRecordSetResource. The ActivityRecordSet stored
|
||||||
|
* as {@link #history} is modified as a result of this call.
|
||||||
|
*
|
||||||
|
* @param requiredContents
|
||||||
|
* The set of strings that each must occur somewhere within the
|
||||||
|
* returned records, whether within the associated username,
|
||||||
|
* the name of some associated object (such as a connection), or any
|
||||||
|
* associated date. If non-empty, any record not matching each of the
|
||||||
|
* strings within the collection will be excluded from the results.
|
||||||
|
*
|
||||||
|
* @param sortPredicates
|
||||||
|
* A list of predicates to apply while sorting the resulting records,
|
||||||
|
* describing the properties involved and the sort order for those
|
||||||
|
* properties.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If an error occurs while applying the given filter criteria or
|
||||||
|
* sort predicates.
|
||||||
|
*/
|
||||||
|
private void applyCriteria(List<String> requiredContents,
|
||||||
|
List<APISortPredicate> sortPredicates) throws GuacamoleException {
|
||||||
|
|
||||||
|
// Restrict to records which contain the specified strings
|
||||||
|
for (String required : requiredContents) {
|
||||||
|
if (!required.isEmpty())
|
||||||
|
history = history.contains(required);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort according to specified ordering
|
||||||
|
for (APISortPredicate predicate : sortPredicates)
|
||||||
|
history = history.sort(predicate.getProperty(), predicate.isDescending());
|
||||||
|
|
||||||
|
// Limit to maximum result size
|
||||||
|
history = history.limit(MAXIMUM_HISTORY_SIZE);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the list of activity records stored within the underlying
|
* Retrieves the list of activity records stored within the underlying
|
||||||
* ActivityRecordSet which match the given, arbitrary criteria. If
|
* ActivityRecordSet which match the given, arbitrary criteria. If
|
||||||
@@ -118,19 +162,9 @@ public abstract class ActivityRecordSetResource<InternalRecordType extends Activ
|
|||||||
@QueryParam("order") List<APISortPredicate> sortPredicates)
|
@QueryParam("order") List<APISortPredicate> sortPredicates)
|
||||||
throws GuacamoleException {
|
throws GuacamoleException {
|
||||||
|
|
||||||
// Restrict to records which contain the specified strings
|
// Apply search/sort criteria
|
||||||
for (String required : requiredContents) {
|
applyCriteria(requiredContents, sortPredicates);
|
||||||
if (!required.isEmpty())
|
|
||||||
history = history.contains(required);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sort according to specified ordering
|
|
||||||
for (APISortPredicate predicate : sortPredicates)
|
|
||||||
history = history.sort(predicate.getProperty(), predicate.isDescending());
|
|
||||||
|
|
||||||
// Limit to maximum result size
|
|
||||||
history = history.limit(MAXIMUM_HISTORY_SIZE);
|
|
||||||
|
|
||||||
// Convert record set to collection of API records
|
// Convert record set to collection of API records
|
||||||
List<ExternalRecordType> apiRecords = new ArrayList<>();
|
List<ExternalRecordType> apiRecords = new ArrayList<>();
|
||||||
for (InternalRecordType record : history.asCollection())
|
for (InternalRecordType record : history.asCollection())
|
||||||
@@ -141,4 +175,72 @@ public abstract class ActivityRecordSetResource<InternalRecordType extends Activ
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves record having the given UUID from among the list of activity
|
||||||
|
* records stored within the underlying ActivityRecordSet which match the
|
||||||
|
* given, arbitrary criteria. If specified, the returned records will also
|
||||||
|
* be sorted according to the given sort predicates. As the number of
|
||||||
|
* activity records retrieved at any given time may be limited by the
|
||||||
|
* extension providing those records, the sorting and search criteria may
|
||||||
|
* impact whether the record having a particular UUID can be located, even
|
||||||
|
* if it is known that the record exists.
|
||||||
|
*
|
||||||
|
* @param uuid
|
||||||
|
* The UUID of the record to retrieve.
|
||||||
|
*
|
||||||
|
* @param requiredContents
|
||||||
|
* The set of strings that each must occur somewhere within the
|
||||||
|
* relevant records, whether within the associated username,
|
||||||
|
* the name of some associated object (such as a connection), or any
|
||||||
|
* associated date. If non-empty, any record not matching each of the
|
||||||
|
* strings within the collection will not be considered.
|
||||||
|
*
|
||||||
|
* @param sortPredicates
|
||||||
|
* A list of predicates to apply while sorting the relevant records,
|
||||||
|
* describing the properties involved and the sort order for those
|
||||||
|
* properties.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The record having the given UUID which matches the provided
|
||||||
|
* criteria.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If an error occurs while applying the given filter criteria or
|
||||||
|
* sort predicates, or if the requested record cannot be found.
|
||||||
|
*/
|
||||||
|
@Path("{uuid}")
|
||||||
|
public ActivityRecordResource getRecord(@PathParam("uuid") String uuid,
|
||||||
|
@QueryParam("contains") List<String> requiredContents,
|
||||||
|
@QueryParam("order") List<APISortPredicate> sortPredicates)
|
||||||
|
throws GuacamoleException {
|
||||||
|
|
||||||
|
// Parse UUID from provided string
|
||||||
|
UUID parsedUUID;
|
||||||
|
try {
|
||||||
|
parsedUUID = UUID.fromString(uuid);
|
||||||
|
}
|
||||||
|
catch (IllegalArgumentException e) {
|
||||||
|
throw new GuacamoleClientException("Invalid UUID.", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply search/sort criteria
|
||||||
|
applyCriteria(requiredContents, sortPredicates);
|
||||||
|
|
||||||
|
// Locate record having given UUID among all visible records
|
||||||
|
for (InternalRecordType record : history.asCollection()) {
|
||||||
|
|
||||||
|
// Ignore records lacking any UUID
|
||||||
|
UUID recordUUID = record.getUUID();
|
||||||
|
if (recordUUID == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (recordUUID.equals(parsedUUID))
|
||||||
|
return new ActivityRecordResource(record);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new GuacamoleResourceNotFoundException("No such history entry.");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user