/*
* Copyright 2015 JBoss, by Red Hat, Inc
*
* Licensed 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.uberfire.ext.security.server.io;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.nio.charset.Charset;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.jboss.errai.security.shared.api.RoleImpl;
import org.jboss.errai.security.shared.api.identity.User;
import org.jboss.errai.security.shared.api.identity.UserImpl;
import org.jboss.errai.security.shared.service.AuthenticationService;
import org.uberfire.backend.server.security.FileSystemResourceAdaptor;
import org.uberfire.commons.lifecycle.PriorityDisposableRegistry;
import org.uberfire.io.IOService;
import org.uberfire.java.nio.IOException;
import org.uberfire.java.nio.channels.SeekableByteChannel;
import org.uberfire.java.nio.file.AtomicMoveNotSupportedException;
import org.uberfire.java.nio.file.CopyOption;
import org.uberfire.java.nio.file.DeleteOption;
import org.uberfire.java.nio.file.DirectoryNotEmptyException;
import org.uberfire.java.nio.file.DirectoryStream;
import org.uberfire.java.nio.file.FileAlreadyExistsException;
import org.uberfire.java.nio.file.FileSystem;
import org.uberfire.java.nio.file.FileSystemAlreadyExistsException;
import org.uberfire.java.nio.file.FileSystemNotFoundException;
import org.uberfire.java.nio.file.NoSuchFileException;
import org.uberfire.java.nio.file.NotDirectoryException;
import org.uberfire.java.nio.file.OpenOption;
import org.uberfire.java.nio.file.Option;
import org.uberfire.java.nio.file.Path;
import org.uberfire.java.nio.file.ProviderNotFoundException;
import org.uberfire.java.nio.file.attribute.FileAttribute;
import org.uberfire.java.nio.file.attribute.FileAttributeView;
import org.uberfire.java.nio.file.attribute.FileTime;
import org.uberfire.security.Resource;
import org.uberfire.security.authz.AuthorizationManager;
import static java.util.Arrays.asList;
import static org.uberfire.commons.validation.PortablePreconditions.checkNotNull;
public class IOSecurityService implements IOService {
private final IOService service;
private final AuthenticationService authenticationService;
private final AuthorizationManager authManager;
public IOSecurityService(final IOService service,
final AuthenticationService authenticationService,
final AuthorizationManager authManager) {
this.authManager = checkNotNull("authManager",
authManager);
this.service = checkNotNull("service",
service);
this.authenticationService = checkNotNull("provider",
authenticationService);
PriorityDisposableRegistry.register(this);
}
@Override
public void dispose() {
}
@Override
public int priority() {
return service.priority() + 1;
}
@Override
public void startBatch(FileSystem fs) {
if (!authManager.authorize(toResource(fs),
getUser())) {
throw new SecurityException();
}
service.startBatch(fs);
}
@Override
public void startBatch(FileSystem[] fss,
Option... options) {
for (FileSystem fs : fss) {
if (!authManager.authorize(toResource(fs),
getUser())) {
throw new SecurityException();
}
}
service.startBatch(fss,
options);
}
@Override
public void startBatch(FileSystem fs,
Option... options) {
if (!authManager.authorize(toResource(fs),
getUser())) {
throw new SecurityException();
}
service.startBatch(fs,
options);
}
@Override
public void startBatch(FileSystem... fss) {
for (FileSystem fs : fss) {
if (!authManager.authorize(toResource(fs),
getUser())) {
throw new SecurityException();
}
}
service.startBatch(fss);
}
@Override
public void endBatch() {
service.endBatch();
}
@Override
public FileAttribute<?>[] convert(Map<String, ?> attrs) {
return service.convert(attrs);
}
@Override
public Path get(String first,
String... more) throws IllegalArgumentException {
try {
final Path result = service.get(first,
more);
if (!authManager.authorize(toResource(result),
getUser())) {
throw new SecurityException();
}
return result;
} catch (IllegalArgumentException ex) {
throw ex;
}
}
@Override
public Path get(URI uri) throws IllegalArgumentException, FileSystemNotFoundException, SecurityException {
try {
final Path result = service.get(uri);
if (!authManager.authorize(toResource(result),
getUser())) {
throw new SecurityException();
}
return result;
} catch (IllegalArgumentException ex) {
throw ex;
} catch (FileSystemNotFoundException ex) {
throw ex;
}
}
@Override
public Iterable<FileSystem> getFileSystems() {
final Iterable<FileSystem> _result = service.getFileSystems();
final Set<FileSystem> result = new HashSet<FileSystem>();
for (final FileSystem fs : _result) {
if (authManager.authorize(toResource(fs),
getUser())) {
result.add(fs);
}
}
return result;
}
@Override
public FileSystem getFileSystem(URI uri) throws IllegalArgumentException, FileSystemNotFoundException, ProviderNotFoundException, SecurityException {
try {
final FileSystem result = service.getFileSystem(uri);
if (!authManager.authorize(toResource(result),
getUser())) {
throw new SecurityException();
}
return result;
} catch (IllegalArgumentException ex) {
throw ex;
} catch (FileSystemNotFoundException ex) {
throw ex;
} catch (ProviderNotFoundException ex) {
throw ex;
}
}
@Override
public FileSystem newFileSystem(URI uri,
Map<String, ?> env) throws IllegalArgumentException, FileSystemAlreadyExistsException, ProviderNotFoundException, IOException, SecurityException {
try {
final FileSystem fs = service.newFileSystem(uri,
env);
if (!authManager.authorize(toResource(fs),
getUser())) {
service.delete(fs.getPath(null));
throw new SecurityException();
}
return fs;
} catch (IllegalArgumentException ex) {
throw ex;
} catch (FileSystemNotFoundException ex) {
throw ex;
} catch (ProviderNotFoundException ex) {
throw ex;
}
}
@Override
public void onNewFileSystem(NewFileSystemListener listener) {
service.onNewFileSystem(listener);
}
@Override
public InputStream newInputStream(Path path,
OpenOption... options) throws IllegalArgumentException, NoSuchFileException, UnsupportedOperationException, IOException, SecurityException {
if (!authManager.authorize(toResource(path),
getUser())) {
throw new SecurityException();
}
return service.newInputStream(path,
options);
}
@Override
public OutputStream newOutputStream(Path path,
OpenOption... options) throws IllegalArgumentException, UnsupportedOperationException, IOException, SecurityException {
if (!authManager.authorize(toResource(path),
getUser())) {
throw new SecurityException();
}
return service.newOutputStream(path,
options);
}
@Override
public SeekableByteChannel newByteChannel(Path path,
OpenOption... options) throws IllegalArgumentException, UnsupportedOperationException, FileAlreadyExistsException, IOException, SecurityException {
if (!authManager.authorize(toResource(path),
getUser())) {
throw new SecurityException();
}
return service.newByteChannel(path,
options);
}
@Override
public SeekableByteChannel newByteChannel(Path path,
Set<? extends OpenOption> options,
FileAttribute<?>... attrs) throws IllegalArgumentException, UnsupportedOperationException, FileAlreadyExistsException, IOException, SecurityException {
if (!authManager.authorize(toResource(path),
getUser())) {
throw new SecurityException();
}
return service.newByteChannel(path,
options,
attrs);
}
@Override
public DirectoryStream<Path> newDirectoryStream(Path dir) throws IllegalArgumentException, NotDirectoryException, IOException, SecurityException {
if (!authManager.authorize(toResource(dir),
getUser())) {
throw new SecurityException();
}
return service.newDirectoryStream(dir);
}
@Override
public DirectoryStream<Path> newDirectoryStream(Path dir,
DirectoryStream.Filter<Path> filter) throws IllegalArgumentException, NotDirectoryException, IOException, SecurityException {
if (!authManager.authorize(toResource(dir),
getUser())) {
throw new SecurityException();
}
return service.newDirectoryStream(dir,
filter);
}
@Override
public Path createFile(Path path,
FileAttribute<?>... attrs) throws IllegalArgumentException, UnsupportedOperationException, FileAlreadyExistsException, IOException, SecurityException {
if (!authManager.authorize(toResource(path),
getUser())) {
throw new SecurityException();
}
return service.createFile(path,
attrs);
}
@Override
public Path createDirectory(Path dir,
FileAttribute<?>... attrs) throws IllegalArgumentException, UnsupportedOperationException, FileAlreadyExistsException, IOException, SecurityException {
if (!authManager.authorize(toResource(dir),
getUser())) {
throw new SecurityException();
}
return service.createFile(dir,
attrs);
}
@Override
public Path createDirectories(Path dir,
FileAttribute<?>... attrs) throws UnsupportedOperationException, FileAlreadyExistsException, IOException, SecurityException {
if (!authManager.authorize(toResource(dir),
getUser())) {
throw new SecurityException();
}
return service.createDirectories(dir,
attrs);
}
@Override
public Path createDirectory(Path dir,
Map<String, ?> attrs) throws IllegalArgumentException, UnsupportedOperationException, FileAlreadyExistsException, IOException, SecurityException {
if (!authManager.authorize(toResource(dir),
getUser())) {
throw new SecurityException();
}
return service.createDirectory(dir,
attrs);
}
@Override
public Path createDirectories(Path dir,
Map<String, ?> attrs) throws UnsupportedOperationException, FileAlreadyExistsException, IOException, SecurityException {
if (!authManager.authorize(toResource(dir),
getUser())) {
throw new SecurityException();
}
return service.createDirectories(dir,
attrs);
}
@Override
public void delete(Path path,
DeleteOption... options) throws IllegalArgumentException, NoSuchFileException, DirectoryNotEmptyException, IOException, SecurityException {
if (!authManager.authorize(toResource(path),
getUser())) {
throw new SecurityException();
}
service.delete(path,
options);
}
@Override
public boolean deleteIfExists(Path path,
DeleteOption... options) throws IllegalArgumentException, DirectoryNotEmptyException, IOException, SecurityException {
if (!authManager.authorize(toResource(path),
getUser())) {
throw new SecurityException();
}
return service.deleteIfExists(path,
options);
}
@Override
public Path createTempFile(String prefix,
String suffix,
FileAttribute<?>... attrs) throws IllegalArgumentException, UnsupportedOperationException, IOException, SecurityException {
return service.createTempFile(prefix,
suffix,
attrs);
}
@Override
public Path createTempFile(Path dir,
String prefix,
String suffix,
FileAttribute<?>... attrs) throws IllegalArgumentException, UnsupportedOperationException, IOException, SecurityException {
if (!authManager.authorize(toResource(dir),
getUser())) {
throw new SecurityException();
}
return service.createTempFile(dir,
prefix,
suffix,
attrs);
}
@Override
public Path createTempDirectory(String prefix,
FileAttribute<?>... attrs) throws IllegalArgumentException, UnsupportedOperationException, IOException, SecurityException {
return service.createTempDirectory(prefix,
attrs);
}
@Override
public Path createTempDirectory(Path dir,
String prefix,
FileAttribute<?>... attrs) throws IllegalArgumentException, UnsupportedOperationException, IOException, SecurityException {
if (!authManager.authorize(toResource(dir),
getUser())) {
throw new SecurityException();
}
return service.createTempDirectory(dir,
prefix,
attrs);
}
@Override
public Path copy(Path source,
Path target,
CopyOption... options) throws UnsupportedOperationException, FileAlreadyExistsException, DirectoryNotEmptyException, IOException, SecurityException {
if (!authManager.authorize(toResource(source),
getUser())) {
throw new SecurityException();
}
if (!authManager.authorize(toResource(target),
getUser())) {
throw new SecurityException();
}
return service.copy(source,
target,
options);
}
@Override
public Path move(Path source,
Path target,
CopyOption... options) throws UnsupportedOperationException, FileAlreadyExistsException, DirectoryNotEmptyException, AtomicMoveNotSupportedException, IOException, SecurityException {
if (!authManager.authorize(toResource(source),
getUser())) {
throw new SecurityException();
}
if (!authManager.authorize(toResource(target),
getUser())) {
throw new SecurityException();
}
return service.move(source,
target,
options);
}
@Override
public <V extends FileAttributeView> V getFileAttributeView(Path path,
Class<V> type) throws IllegalArgumentException {
if (!authManager.authorize(toResource(path),
getUser())) {
throw new SecurityException();
}
return service.getFileAttributeView(path,
type);
}
@Override
public Map<String, Object> readAttributes(Path path) throws UnsupportedOperationException, NoSuchFileException, IllegalArgumentException, IOException, SecurityException {
if (!authManager.authorize(toResource(path),
getUser())) {
throw new SecurityException();
}
return service.readAttributes(path);
}
@Override
public Map<String, Object> readAttributes(Path path,
String attributes) throws UnsupportedOperationException, NoSuchFileException, IllegalArgumentException, IOException, SecurityException {
if (!authManager.authorize(toResource(path),
getUser())) {
throw new SecurityException();
}
return service.readAttributes(path,
attributes);
}
@Override
public Path setAttributes(Path path,
FileAttribute<?>... attrs) throws UnsupportedOperationException, IllegalArgumentException, ClassCastException, IOException, SecurityException {
if (!authManager.authorize(toResource(path),
getUser())) {
throw new SecurityException();
}
return service.setAttributes(path,
attrs);
}
@Override
public Path setAttributes(Path path,
Map<String, Object> attrs) throws UnsupportedOperationException, IllegalArgumentException, ClassCastException, IOException, SecurityException {
if (!authManager.authorize(toResource(path),
getUser())) {
throw new SecurityException();
}
return service.setAttributes(path,
attrs);
}
@Override
public Path setAttribute(Path path,
String attribute,
Object value) throws UnsupportedOperationException, IllegalArgumentException, ClassCastException, IOException, SecurityException {
if (!authManager.authorize(toResource(path),
getUser())) {
throw new SecurityException();
}
return service.setAttribute(path,
attribute,
value);
}
@Override
public Object getAttribute(Path path,
String attribute) throws UnsupportedOperationException, IllegalArgumentException, IOException, SecurityException {
if (!authManager.authorize(toResource(path),
getUser())) {
throw new SecurityException();
}
return service.getAttribute(path,
attribute);
}
@Override
public FileTime getLastModifiedTime(Path path) throws IllegalArgumentException, IOException, SecurityException {
if (!authManager.authorize(toResource(path),
getUser())) {
throw new SecurityException();
}
return service.getLastModifiedTime(path);
}
@Override
public long size(Path path) throws IllegalArgumentException, IOException, SecurityException {
if (!authManager.authorize(toResource(path),
getUser())) {
throw new SecurityException();
}
return service.size(path);
}
@Override
public boolean exists(Path path) throws IllegalArgumentException, SecurityException {
if (!authManager.authorize(toResource(path),
getUser())) {
throw new SecurityException();
}
return service.exists(path);
}
@Override
public boolean notExists(Path path) throws IllegalArgumentException, SecurityException {
if (!authManager.authorize(toResource(path),
getUser())) {
throw new SecurityException();
}
return service.notExists(path);
}
@Override
public boolean isSameFile(Path path,
Path path2) throws IllegalArgumentException, IOException, SecurityException {
if (!authManager.authorize(toResource(path),
getUser())) {
throw new SecurityException();
}
if (!authManager.authorize(toResource(path2),
getUser())) {
throw new SecurityException();
}
return service.isSameFile(path,
path2);
}
@Override
public BufferedReader newBufferedReader(Path path,
Charset cs) throws IllegalArgumentException, NoSuchFileException, IOException, SecurityException {
if (!authManager.authorize(toResource(path),
getUser())) {
throw new SecurityException();
}
return service.newBufferedReader(path,
cs);
}
@Override
public BufferedWriter newBufferedWriter(Path path,
Charset cs,
OpenOption... options) throws IllegalArgumentException, IOException, UnsupportedOperationException, SecurityException {
if (!authManager.authorize(toResource(path),
getUser())) {
throw new SecurityException();
}
return service.newBufferedWriter(path,
cs,
options);
}
@Override
public long copy(InputStream in,
Path target,
CopyOption... options) throws IOException, FileAlreadyExistsException, DirectoryNotEmptyException, UnsupportedOperationException, SecurityException {
if (!authManager.authorize(toResource(target),
getUser())) {
throw new SecurityException();
}
return service.copy(in,
target,
options);
}
@Override
public long copy(Path source,
OutputStream out) throws IOException, SecurityException {
if (!authManager.authorize(toResource(source),
getUser())) {
throw new SecurityException();
}
return service.copy(source,
out);
}
@Override
public byte[] readAllBytes(Path path) throws IOException, OutOfMemoryError, SecurityException {
if (!authManager.authorize(toResource(path),
getUser())) {
throw new SecurityException();
}
return service.readAllBytes(path);
}
@Override
public List<String> readAllLines(Path path) throws IllegalArgumentException, NoSuchFileException, IOException, SecurityException {
if (!authManager.authorize(toResource(path),
getUser())) {
throw new SecurityException();
}
return service.readAllLines(path);
}
@Override
public List<String> readAllLines(Path path,
Charset cs) throws IllegalArgumentException, NoSuchFileException, IOException, SecurityException {
if (!authManager.authorize(toResource(path),
getUser())) {
throw new SecurityException();
}
return service.readAllLines(path,
cs);
}
@Override
public String readAllString(Path path,
Charset cs) throws IllegalArgumentException, NoSuchFileException, IOException {
if (!authManager.authorize(toResource(path),
getUser())) {
throw new SecurityException();
}
return service.readAllString(path,
cs);
}
@Override
public String readAllString(Path path) throws IllegalArgumentException, NoSuchFileException, IOException {
if (!authManager.authorize(toResource(path),
getUser())) {
throw new SecurityException();
}
return service.readAllString(path);
}
@Override
public Path write(Path path,
byte[] bytes,
OpenOption... options) throws IOException, UnsupportedOperationException, SecurityException {
if (!authManager.authorize(toResource(path),
getUser())) {
throw new SecurityException();
}
return service.write(path,
bytes);
}
@Override
public Path write(Path path,
byte[] bytes,
Map<String, ?> attrs,
OpenOption... options) throws IOException, UnsupportedOperationException, SecurityException {
if (!authManager.authorize(toResource(path),
getUser())) {
throw new SecurityException();
}
return service.write(path,
bytes,
attrs,
options);
}
@Override
public Path write(Path path,
byte[] bytes,
Set<? extends OpenOption> options,
FileAttribute<?>... attrs) throws IllegalArgumentException, IOException, UnsupportedOperationException {
if (!authManager.authorize(toResource(path),
getUser())) {
throw new SecurityException();
}
return service.write(path,
bytes,
options,
attrs);
}
@Override
public Path write(Path path,
Iterable<? extends CharSequence> lines,
Charset cs,
OpenOption... options) throws IllegalArgumentException, IOException, UnsupportedOperationException, SecurityException {
if (!authManager.authorize(toResource(path),
getUser())) {
throw new SecurityException();
}
return service.write(path,
lines,
cs,
options);
}
@Override
public Path write(Path path,
String content,
OpenOption... options) throws IllegalArgumentException, IOException, UnsupportedOperationException {
if (!authManager.authorize(toResource(path),
getUser())) {
throw new SecurityException();
}
return service.write(path,
content,
options);
}
@Override
public Path write(Path path,
String content,
Charset cs,
OpenOption... options) throws IllegalArgumentException, IOException, UnsupportedOperationException {
if (!authManager.authorize(toResource(path),
getUser())) {
throw new SecurityException();
}
return service.write(path,
content,
cs,
options);
}
@Override
public Path write(Path path,
String content,
Set<? extends OpenOption> options,
FileAttribute<?>... attrs) throws IllegalArgumentException, IOException, UnsupportedOperationException {
if (!authManager.authorize(toResource(path),
getUser())) {
throw new SecurityException();
}
return service.write(path,
content,
options,
attrs);
}
@Override
public Path write(Path path,
String content,
Charset cs,
Set<? extends OpenOption> options,
FileAttribute<?>... attrs) throws IllegalArgumentException, IOException, UnsupportedOperationException {
if (!authManager.authorize(toResource(path),
getUser())) {
throw new SecurityException();
}
return service.write(path,
content,
cs,
options,
attrs);
}
@Override
public Path write(Path path,
String content,
Map<String, ?> attrs,
OpenOption... options) throws IllegalArgumentException, IOException, UnsupportedOperationException {
if (!authManager.authorize(toResource(path),
getUser())) {
throw new SecurityException();
}
return service.write(path,
content,
attrs,
options);
}
@Override
public Path write(Path path,
String content,
Charset cs,
Map<String, ?> attrs,
OpenOption... options) throws IllegalArgumentException, IOException, UnsupportedOperationException {
if (!authManager.authorize(toResource(path),
getUser())) {
throw new SecurityException();
}
return service.write(path,
content,
cs,
attrs,
options);
}
private Resource toResource(final FileSystem fs) {
return new FileSystemResourceAdaptor(fs);
}
private Resource toResource(final Path path) {
return new FileSystemResourceAdaptor(path.getFileSystem());
}
private User getUser() {
try {
return authenticationService.getUser();
} catch (final IllegalStateException ex) {
return new UserImpl("system",
asList(new RoleImpl("admin")));
}
}
}