java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/GPSFixStoreListenerTest.java
... ...
@@ -33,9 +33,9 @@ public class GPSFixStoreListenerTest extends AbstractGPSFixStoreTest {
33 33
CyclicBarrier barrier = new CyclicBarrier(2);
34 34
// We need 3 listener instances to guarantee that the iterator isn't finished
35 35
// when adding another listener in the thread below.
36
- store.addListener(new ListenerAwaitingBarier(barrier), device);
37
- store.addListener(new ListenerAwaitingBarier(barrier), device);
38
- store.addListener(new ListenerAwaitingBarier(barrier), device);
36
+ store.addListener(new ListenerAwaitingBarrier(barrier), device);
37
+ store.addListener(new ListenerAwaitingBarrier(barrier), device);
38
+ store.addListener(new ListenerAwaitingBarrier(barrier), device);
39 39
40 40
Thread thread = new Thread() {
41 41
public void run() {
... ...
@@ -63,11 +63,11 @@ public class GPSFixStoreListenerTest extends AbstractGPSFixStoreTest {
63 63
}
64 64
}
65 65
66
- private static class ListenerAwaitingBarier implements FixReceivedListener<GPSFixMoving> {
66
+ private static class ListenerAwaitingBarrier implements FixReceivedListener<GPSFixMoving> {
67 67
68 68
private final CyclicBarrier barrier;
69 69
70
- public ListenerAwaitingBarier(CyclicBarrier barrier) {
70
+ public ListenerAwaitingBarrier(CyclicBarrier barrier) {
71 71
this.barrier = barrier;
72 72
}
73 73
java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/fixtracker/FixLoaderAndTracker.java
... ...
@@ -191,7 +191,6 @@ public class FixLoaderAndTracker implements TrackingDataLoader {
191 191
@Override
192 192
public Iterable<RegattaAndRaceIdentifier> fixReceived(DeviceIdentifier device, Timed fix) {
193 193
Set<RegattaAndRaceIdentifier> maneuverChanged = new HashSet<>();
194
-
195 194
if (!preemptiveStopRequested.get() && trackedRace.getStartOfTracking() != null) {
196 195
final TimePoint timePoint = fix.getTimePoint();
197 196
deviceMappings.forEachMappingOfDeviceIncludingTimePoint(device, fix.getTimePoint(),
java/com.sap.sailing.server.gateway.test/.settings/org.eclipse.core.resources.prefs
... ...
@@ -0,0 +1,2 @@
1
+eclipse.preferences.version=1
2
+encoding//src/com/sap/sailing/server/gateway/test/jaxrs/CompetitorsResourceTest.java=UTF-8
java/com.sap.sailing.server.gateway.test/META-INF/MANIFEST.MF
... ...
@@ -14,7 +14,8 @@ Require-Bundle: org.mockito.mockito-core;bundle-version="1.9.5",
14 14
com.sap.sailing.domain.racelogtrackingadapter.testsupport,
15 15
com.sap.sse.common,
16 16
com.sun.jersey,
17
- org.apache.commons.io;bundle-version="2.2.0"
17
+ org.apache.commons.io;bundle-version="2.2.0",
18
+ com.sap.sse.security.testsupport
18 19
Import-Package: com.sap.sailing.domain.common.impl,
19 20
com.sap.sailing.domain.persistence.impl,
20 21
com.sap.sailing.server.impl,
java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/AbstractJaxRsApiTest.java
... ...
@@ -10,8 +10,6 @@ import java.util.ArrayList;
10 10
import java.util.Collections;
11 11
import java.util.Date;
12 12
import java.util.List;
13
-import java.util.UUID;
14
-import java.util.concurrent.Callable;
15 13
16 14
import javax.ws.rs.core.Response;
17 15
... ...
@@ -21,8 +19,6 @@ import org.apache.shiro.subject.Subject;
21 19
import org.apache.shiro.subject.support.SubjectThreadState;
22 20
import org.apache.shiro.util.ThreadState;
23 21
import org.mockito.Mockito;
24
-import org.mockito.invocation.InvocationOnMock;
25
-import org.mockito.stubbing.Answer;
26 22
27 23
import com.sap.sailing.domain.base.Competitor;
28 24
import com.sap.sailing.domain.base.impl.CompetitorImpl;
... ...
@@ -39,13 +35,11 @@ import com.sap.sse.common.TimePoint;
39 35
import com.sap.sse.common.impl.MillisecondsTimePoint;
40 36
import com.sap.sse.mongodb.MongoDBConfiguration;
41 37
import com.sap.sse.mongodb.MongoDBService;
42
-import com.sap.sse.security.Action;
43 38
import com.sap.sse.security.SecurityService;
44 39
import com.sap.sse.security.shared.OwnershipAnnotation;
45
-import com.sap.sse.security.shared.WithQualifiedObjectIdentifier;
46 40
import com.sap.sse.security.shared.impl.Ownership;
47 41
import com.sap.sse.security.shared.impl.User;
48
-import com.sap.sse.security.shared.impl.UserGroupImpl;
42
+import com.sap.sse.security.testsupport.SecurityServiceMockFactory;
49 43
50 44
public abstract class AbstractJaxRsApiTest {
51 45
protected RacingEventService racingEventService;
... ...
@@ -60,52 +54,17 @@ public abstract class AbstractJaxRsApiTest {
60 54
61 55
protected static SimpleDateFormat TIMEPOINT_FORMATTER = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
62 56
63
- @SuppressWarnings("unchecked")
64 57
public void setUp() throws Exception {
65 58
service = MongoDBConfiguration.getDefaultTestConfiguration().getService();
66 59
service.getDB().drop();
67 60
racingEventService = Mockito.spy(new RacingEventServiceImpl(/* clearPersistentCompetitorStore */ true,
68 61
new MockSmartphoneUuidServiceFinderFactory(), /* restoreTrackedRaces */ false));
69
-
70
- UserGroupImpl defaultTenant = new UserGroupImpl(new UUID(0, 1), "defaultTenant");
71
-
72
- securityService = Mockito.mock(SecurityService.class);
73 62
SecurityManager securityManager = Mockito.mock(org.apache.shiro.mgt.SecurityManager.class);
74 63
Subject fakeSubject = Mockito.mock(Subject.class);
75
-
64
+ Mockito.doReturn(true).when(fakeSubject).isAuthenticated();
76 65
SecurityUtils.setSecurityManager(securityManager);
77 66
Mockito.doReturn(fakeSubject).when(securityManager).createSubject(Mockito.any());
78
-
79
- Mockito.doReturn(defaultTenant).when(securityService).getDefaultTenant();
80
-
81
- Mockito.doAnswer(new Answer<Object>() {
82
- @Override
83
- public Object answer(InvocationOnMock invocation) throws Throwable {
84
- return invocation.getArgumentAt(4, Callable.class).call();
85
- }
86
- }).when(securityService).setOwnershipCheckPermissionForObjectCreationAndRevertOnError(
87
- Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any(Action.class));
88
- Mockito.doAnswer(new Answer<Object>() {
89
- @SuppressWarnings("rawtypes")
90
- @Override
91
- public Object answer(InvocationOnMock invocation) throws Throwable {
92
- for (Object arg : invocation.getArguments()) {
93
- if (arg instanceof Callable) {
94
- return ((Callable) arg).call();
95
- }
96
- }
97
- return null;
98
- }
99
- }).when(securityService).setOwnershipCheckPermissionForObjectCreationAndRevertOnError(Mockito.any(),
100
- Mockito.any(), Mockito.any(), Mockito.any(Callable.class));
101
-
102
- Mockito.doReturn(true).when(securityService)
103
- .hasCurrentUserReadPermission(Mockito.any(WithQualifiedObjectIdentifier.class));
104
-
105
- Mockito.doNothing().when(securityService).checkCurrentUserReadPermission(Mockito.any());
106
-
107
- Mockito.doReturn(true).when(fakeSubject).isAuthenticated();
108
-
67
+ securityService = SecurityServiceMockFactory.mockSecurityService();
109 68
OwnershipAnnotation mockedOwnership = Mockito.mock(OwnershipAnnotation.class);
110 69
Ownership ownership = Mockito.mock(Ownership.class);
111 70
Mockito.doReturn(mockedOwnership).when(securityService).getOwnership(Mockito.any());
java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/CompetitorsResourceTeamImageTest.java
... ...
@@ -39,7 +39,7 @@ public class CompetitorsResourceTeamImageTest extends AbstractJaxRsApiTest {
39 39
@Before
40 40
public void setUpSubClass() throws Exception {
41 41
super.setUp();
42
- storageService = AmazonS3TestSupport.createService();
42
+ storageService = AmazonS3TestSupport.createService(securityService);
43 43
FileStorageManagementService fsmsMock = mock(FileStorageManagementService.class);
44 44
doReturn(fsmsMock).when(racingEventService).getFileStorageManagementService();
45 45
doReturn(storageService).when(fsmsMock).getActiveFileStorageService();
... ...
@@ -52,26 +52,21 @@ public class CompetitorsResourceTeamImageTest extends AbstractJaxRsApiTest {
52 52
@Test
53 53
public void storeAndRemoveTeamImage() throws URISyntaxException, ParseException, MalformedURLException,
54 54
IOException, OperationFailedException, InvalidPropertiesException {
55
- //set team image
55
+ // set team image
56 56
String fileExtension = teamImageFile.substring(teamImageFile.lastIndexOf("."));;
57 57
InputStream stream = getClass().getResourceAsStream("/" + teamImageFile);
58
-
59 58
// this is not ideal, as this #available() is not supposed to be used for getting the file size
60 59
// however, working with a File() descriptor does not work, as when running via maven/tycho the
61 60
// URL has the bundleresource:// scheme instead of file:, which File() can't handle
62 61
long length = stream.available();
63
-
64 62
String jsonString = competitorsResource.setTeamImage(id, stream, fileExtension, length, null, null);
65
-
66
- //now download and compare
63
+ // now download and compare
67 64
JSONObject json = (JSONObject) JSONValue.parseWithException(jsonString);
68 65
String imageUriString = (String) json.get(DeviceMappingConstants.JSON_TEAM_IMAGE_URI);
69 66
URI imageUri = new URI(imageUriString);
70
-
71 67
InputStream downloadStream = imageUri.toURL().openStream();
72 68
stream = getClass().getResourceAsStream("/" + teamImageFile);
73 69
IOUtils.contentEquals(downloadStream, stream);
74
-
75 70
storageService.removeFile(imageUri);
76 71
}
77 72
}
java/com.sap.sse.filestorage.test/META-INF/MANIFEST.MF
... ...
@@ -13,7 +13,8 @@ Require-Bundle: org.hamcrest;bundle-version="1.1.0",
13 13
com.sap.sse.replication;bundle-version="1.0.0",
14 14
org.mockito.mockito-core;bundle-version="1.10.14",
15 15
org.apache.shiro.core;bundle-version="1.2.2",
16
- org.objenesis;bundle-version="2.1.0"
16
+ org.objenesis;bundle-version="2.1.0",
17
+ com.sap.sse.security.testsupport
17 18
Import-Package: org.apache.commons.logging,
18 19
org.slf4j;version="1.6.4"
19 20
Automatic-Module-Name: com.sap.sse.filestorage.test
java/com.sap.sse.filestorage.test/src/com/sap/sse/filestorage/services/test/AmazonS3Test.java
... ...
@@ -18,18 +18,18 @@ import com.sap.sse.filestorage.FileStorageService;
18 18
import com.sap.sse.filestorage.InvalidPropertiesException;
19 19
import com.sap.sse.filestorage.OperationFailedException;
20 20
import com.sap.sse.filestorage.testsupport.AmazonS3TestSupport;
21
+import com.sap.sse.security.testsupport.SecurityServiceMockFactory;
21 22
22 23
public class AmazonS3Test {
23 24
@Before
24 25
public void setup() throws InvalidPropertiesException {
25 26
setUpSecurity();
26
- storageService = AmazonS3TestSupport.createService();
27
+ storageService = AmazonS3TestSupport.createService(SecurityServiceMockFactory.mockSecurityService());
27 28
}
28 29
29 30
private void setUpSecurity() {
30 31
org.apache.shiro.mgt.SecurityManager securityManager = Mockito.mock(org.apache.shiro.mgt.SecurityManager.class);
31 32
Subject fakeSubject = Mockito.mock(Subject.class);
32
-
33 33
SecurityUtils.setSecurityManager(securityManager);
34 34
Mockito.doReturn(fakeSubject).when(securityManager).createSubject(Mockito.any());
35 35
Mockito.doReturn(true).when(fakeSubject).isAuthenticated();
... ...
@@ -42,14 +42,11 @@ public class AmazonS3Test {
42 42
@Test
43 43
public void testStoreAndRemoveFileTest() throws URISyntaxException, IOException, OperationFailedException, InvalidPropertiesException {
44 44
InputStream stream = getClass().getClassLoader().getResourceAsStream(teamImageFile);
45
-
46 45
// this is not ideal, as this #available() is not supposed to be used for getting the file size
47 46
// however, working with a File() descriptor does not work, as when running via maven/tycho the
48 47
// URL has the bundleresource:// scheme instead of file:, which File() can't handle
49 48
long length = stream.available();
50
-
51 49
URI uri = storageService.storeFile(stream, teamImageFile, length);
52
-
53 50
InputStream downloadStream = uri.toURL().openStream();
54 51
stream = getClass().getClassLoader().getResourceAsStream(teamImageFile);
55 52
try {
java/com.sap.sse.filestorage/META-INF/MANIFEST.MF
... ...
@@ -25,5 +25,6 @@ Require-Bundle: org.apache.servicemix.bundles.aws-java-sdk;bundle-version="1.9.8
25 25
org.apache.commons.io,
26 26
org.mongodb.mongo-java-driver;bundle-version="3.6.4",
27 27
org.apache.shiro.core,
28
- com.sap.sailing.domain.common
28
+ com.sap.sailing.domain.common,
29
+ com.sap.sse.security
29 30
Automatic-Module-Name: com.sap.sse.filestorage
java/com.sap.sse.filestorage/src/com/sap/sse/filestorage/impl/Activator.java
... ...
@@ -31,11 +31,11 @@ public class Activator implements BundleActivator {
31 31
32 32
Dictionary<String, String> dict = new Hashtable<>();
33 33
dict.put(TypeBasedServiceFinder.TYPE, AmazonS3FileStorageServiceImpl.NAME);
34
- context.registerService(FileStorageService.class, new AmazonS3FileStorageServiceImpl(), dict);
34
+ context.registerService(FileStorageService.class, new AmazonS3FileStorageServiceImpl(context), dict);
35 35
36 36
Dictionary<String, String> localStorageDict = new Hashtable<>();
37 37
localStorageDict.put(TypeBasedServiceFinder.TYPE, LocalFileStorageServiceImpl.NAME);
38
- context.registerService(FileStorageService.class, new LocalFileStorageServiceImpl(), localStorageDict);
38
+ context.registerService(FileStorageService.class, new LocalFileStorageServiceImpl(context), localStorageDict);
39 39
40 40
// register mgmt service
41 41
FileStorageManagementServiceImpl mgmtService = new FileStorageManagementServiceImpl(
java/com.sap.sse.filestorage/src/com/sap/sse/filestorage/impl/AmazonS3FileStorageServiceImpl.java
... ...
@@ -9,6 +9,7 @@ import java.util.logging.Logger;
9 9
10 10
import org.apache.shiro.SecurityUtils;
11 11
import org.apache.shiro.authz.UnauthorizedException;
12
+import org.osgi.framework.BundleContext;
12 13
13 14
import com.amazonaws.AmazonClientException;
14 15
import com.amazonaws.auth.AWSCredentials;
... ...
@@ -53,8 +54,8 @@ public class AmazonS3FileStorageServiceImpl extends BaseFileStorageServiceImpl i
53 54
private final FileStorageServicePropertyImpl bucketName = new FileStorageServicePropertyImpl("bucketName", true,
54 55
"s3BucketNameDesc");
55 56
56
- public AmazonS3FileStorageServiceImpl() {
57
- super(NAME, "s3Desc");
57
+ public AmazonS3FileStorageServiceImpl(BundleContext bundleContext) {
58
+ super(NAME, "s3Desc", bundleContext);
58 59
addProperties(accessId, accessKey, bucketName);
59 60
}
60 61
... ...
@@ -98,48 +99,42 @@ public class AmazonS3FileStorageServiceImpl extends BaseFileStorageServiceImpl i
98 99
final ObjectMetadata metadata = new ObjectMetadata();
99 100
metadata.setContentLength(lengthInBytes);
100 101
final String key = getKey(fileExtension);
101
-
102
- SecurityUtils.getSubject().checkPermission(
103
- SecuredDomainType.FILE_STORAGE.getStringPermissionForTypeRelativeIdentifier(DefaultActions.CREATE,
104
- new TypeRelativeObjectIdentifier(key)));
105
-
106
- final PutObjectRequest request = new PutObjectRequest(bucketName.getValue(), key, is, metadata)
107
- .withCannedAcl(CannedAccessControlList.PublicRead);
108
- final AmazonS3Client s3Client = createS3Client();
109
- try {
110
- s3Client.putObject(request);
111
- } catch (AmazonClientException e) {
112
- logger.log(Level.SEVERE, "Could not store file", e);
113
- throw new OperationFailedException(e.getMessage(), e);
114
- }
115
- URI uri = getUri(key);
116
- logger.info("Stored file " + uri);
117
- return uri;
102
+ return getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError(
103
+ SecuredDomainType.FILE_STORAGE, new TypeRelativeObjectIdentifier(key),
104
+ key, () -> {
105
+ final PutObjectRequest request = new PutObjectRequest(bucketName.getValue(), key, is, metadata)
106
+ .withCannedAcl(CannedAccessControlList.PublicRead);
107
+ final AmazonS3Client s3Client = createS3Client();
108
+ try {
109
+ s3Client.putObject(request);
110
+ } catch (AmazonClientException e) {
111
+ logger.log(Level.SEVERE, "Could not store file", e);
112
+ throw new OperationFailedException(e.getMessage(), e);
113
+ }
114
+ URI uri = getUri(key);
115
+ logger.info("Stored file " + uri);
116
+ return uri;
117
+ });
118 118
}
119 119
120 120
@Override
121 121
public void removeFile(URI uri) throws InvalidPropertiesException, OperationFailedException, UnauthorizedException {
122 122
String key = uri.getPath().substring(uri.getPath().lastIndexOf("/")+1);
123
-
124
- SecurityUtils.getSubject().checkPermission(
125
- SecuredDomainType.FILE_STORAGE.getStringPermissionForTypeRelativeIdentifier(DefaultActions.DELETE,
126
- new TypeRelativeObjectIdentifier(key)));
127
-
128
- AmazonS3Client s3Client = createS3Client();
129
-
130
- try {
131
- s3Client.deleteObject(new DeleteObjectRequest(bucketName.getValue(), key));
132
- } catch (AmazonClientException e) {
133
- throw new OperationFailedException("Could not remove file " + uri.toString(), e);
134
- }
135
- logger.info("Removed file " + uri);
123
+ getSecurityService().checkPermissionAndDeleteOwnershipForObjectRemoval(SecuredDomainType.FILE_STORAGE.getQualifiedObjectIdentifier(
124
+ new TypeRelativeObjectIdentifier(key)), () -> {
125
+ AmazonS3Client s3Client = createS3Client();
126
+ try {
127
+ s3Client.deleteObject(new DeleteObjectRequest(bucketName.getValue(), key));
128
+ } catch (AmazonClientException e) {
129
+ throw new OperationFailedException("Could not remove file " + uri.toString(), e);
130
+ }
131
+ logger.info("Removed file " + uri);
132
+ });
136 133
}
137 134
138 135
@Override
139 136
public void testProperties() throws InvalidPropertiesException {
140 137
AmazonS3Client s3 = createS3Client();
141
-
142
-
143 138
if (bucketName.getValue().equals("")) {
144 139
throw new InvalidPropertiesException("empty bucketname is not allowed");
145 140
}
... ...
@@ -152,7 +147,6 @@ public class AmazonS3FileStorageServiceImpl extends BaseFileStorageServiceImpl i
152 147
new Pair<FileStorageServiceProperty, String>(accessId, "seems to be invalid"),
153 148
new Pair<FileStorageServiceProperty, String>(accessKey, "seems to be invalid"));
154 149
}
155
-
156 150
// test if bucket exists
157 151
if (!s3.doesBucketExist(bucketName.getValue())) {
158 152
throw new InvalidPropertiesException("invalid bucket", new Pair<FileStorageServiceProperty, String>(
... ...
@@ -163,9 +157,8 @@ public class AmazonS3FileStorageServiceImpl extends BaseFileStorageServiceImpl i
163 157
@Override
164 158
public void doPermissionCheckForGetFile(URI uri) throws UnauthorizedException {
165 159
String key = uri.getPath().substring(uri.getPath().lastIndexOf("/") + 1);
166
-
167 160
SecurityUtils.getSubject().checkPermission(
168
- SecuredDomainType.FILE_STORAGE.getStringPermissionForTypeRelativeIdentifier(DefaultActions.DELETE,
161
+ SecuredDomainType.FILE_STORAGE.getStringPermissionForTypeRelativeIdentifier(DefaultActions.READ,
169 162
new TypeRelativeObjectIdentifier(key)));
170 163
}
171 164
}
java/com.sap.sse.filestorage/src/com/sap/sse/filestorage/impl/BaseFileStorageServiceImpl.java
... ...
@@ -4,20 +4,35 @@ import java.util.LinkedHashMap;
4 4
import java.util.Locale;
5 5
import java.util.Map;
6 6
7
+import org.osgi.framework.BundleContext;
8
+import org.osgi.util.tracker.ServiceTracker;
9
+
7 10
import com.sap.sse.common.IsManagedByCache;
8 11
import com.sap.sse.filestorage.FileStorageService;
9 12
import com.sap.sse.filestorage.FileStorageServiceProperty;
10 13
import com.sap.sse.filestorage.FileStorageServiceResolver;
14
+import com.sap.sse.security.SecurityService;
15
+import com.sap.sse.util.ServiceTrackerFactory;
11 16
12 17
public abstract class BaseFileStorageServiceImpl implements FileStorageService {
13 18
private static final long serialVersionUID = 7787261863522200165L;
14 19
private final String name;
15 20
private final String descriptionKey;
16 21
protected final Map<String, FileStorageServicePropertyImpl> propertiesByNameInInsertionOrder = new LinkedHashMap<>();
22
+ private final ServiceTracker<SecurityService, SecurityService> securityServiceTracker;
17 23
18
- protected BaseFileStorageServiceImpl(String name, String descriptionKey) {
24
+ protected BaseFileStorageServiceImpl(String name, String descriptionKey, BundleContext bundleContext) {
19 25
this.name = name;
20 26
this.descriptionKey = descriptionKey;
27
+ this.securityServiceTracker = bundleContext == null ? null : ServiceTrackerFactory.createAndOpen(bundleContext, SecurityService.class);
28
+ }
29
+
30
+ protected SecurityService getSecurityService() {
31
+ try {
32
+ return securityServiceTracker.waitForService(0);
33
+ } catch (InterruptedException e) {
34
+ throw new RuntimeException(e);
35
+ }
21 36
}
22 37
23 38
protected void addProperties(FileStorageServicePropertyImpl... properties) {
java/com.sap.sse.filestorage/src/com/sap/sse/filestorage/impl/LocalFileStorageServiceImpl.java
... ...
@@ -15,6 +15,7 @@ import java.util.logging.Logger;
15 15
import org.apache.commons.io.IOUtils;
16 16
import org.apache.shiro.SecurityUtils;
17 17
import org.apache.shiro.authz.UnauthorizedException;
18
+import org.osgi.framework.BundleContext;
18 19
19 20
import com.sap.sailing.domain.common.security.SecuredDomainType;
20 21
import com.sap.sse.common.Util.Pair;
... ...
@@ -54,44 +55,38 @@ public class LocalFileStorageServiceImpl extends BaseFileStorageServiceImpl impl
54 55
private final FileStorageServicePropertyImpl localPath = new FileStorageServicePropertyImpl("localPath", true, "localLocalPathDesc");
55 56
56 57
57
- protected LocalFileStorageServiceImpl() {
58
- super(NAME, "localDesc");
58
+ protected LocalFileStorageServiceImpl(BundleContext bundleContext) {
59
+ super(NAME, "localDesc", bundleContext);
59 60
addProperties(baseURL, localPath);
60 61
}
61 62
62 63
@Override
63 64
public URI storeFile(InputStream is, String fileExtension, long lengthInBytes)
64 65
throws IOException, UnauthorizedException {
65
- OutputStream outputStream = null;
66 66
String fileName = getKey(fileExtension);
67 67
String pathToFile = localPath.getValue() + "/" + fileName;
68
- SecurityUtils.getSubject().checkPermission(
69
- SecuredDomainType.FILE_STORAGE.getStringPermissionForTypeRelativeIdentifier(DefaultActions.CREATE,
70
- new TypeRelativeObjectIdentifier(pathToFile)));
71
-
72
- File outputFile = new File(pathToFile);
73
- logger.log(Level.FINE, "Storing file in " + outputFile.getAbsolutePath());
74
- outputStream = new FileOutputStream(outputFile);
75
-
76
- try {
77
- int read = 0;
78
- byte[] bytes = new byte[1024];
79
-
80
- while ((read = is.read(bytes)) != -1) {
81
- outputStream.write(bytes, 0, read);
82
- }
83
-
84
- } finally {
85
- if (is != null) {
86
- is.close();
87
- }
88
- if (outputStream != null) {
89
- outputStream.flush();
90
- outputStream.close();
91
- }
92
- }
93
-
94
- return getUri(fileName);
68
+ return getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError(SecuredDomainType.FILE_STORAGE,
69
+ new TypeRelativeObjectIdentifier(pathToFile), pathToFile, () -> {
70
+ final File outputFile = new File(pathToFile);
71
+ logger.log(Level.FINE, "Storing file in " + outputFile.getAbsolutePath());
72
+ final OutputStream outputStream = new FileOutputStream(outputFile);
73
+ try {
74
+ int read = 0;
75
+ byte[] bytes = new byte[1024];
76
+ while ((read = is.read(bytes)) != -1) {
77
+ outputStream.write(bytes, 0, read);
78
+ }
79
+ } finally {
80
+ if (is != null) {
81
+ is.close();
82
+ }
83
+ if (outputStream != null) {
84
+ outputStream.flush();
85
+ outputStream.close();
86
+ }
87
+ }
88
+ return getUri(fileName);
89
+ });
95 90
}
96 91
97 92
private static String getKey(String fileEnding) {
... ...
@@ -118,16 +113,13 @@ public class LocalFileStorageServiceImpl extends BaseFileStorageServiceImpl impl
118 113
if (!file.exists()) {
119 114
throw new FileNotFoundException(uri.toString());
120 115
}
121
-
122
- SecurityUtils.getSubject()
123
- .checkPermission(SecuredDomainType.FILE_STORAGE.getStringPermissionForTypeRelativeIdentifier(
124
- DefaultActions.DELETE,
125
- new TypeRelativeObjectIdentifier(pathToFile)));
126
-
127
- if (!file.delete()) {
128
- logger.warning("Could not delete file with path " + filePath);
129
- throw new IOException("Could not delete file with path "+filePath);
130
- }
116
+ getSecurityService().checkPermissionAndDeleteOwnershipForObjectRemoval(SecuredDomainType.FILE_STORAGE.
117
+ getQualifiedObjectIdentifier(new TypeRelativeObjectIdentifier(pathToFile)), () -> {
118
+ if (!file.delete()) {
119
+ logger.warning("Could not delete file with path " + filePath);
120
+ throw new IOException("Could not delete file with path "+filePath);
121
+ }
122
+ });
131 123
}
132 124
133 125
@Override
java/com.sap.sse.filestorage/src/com/sap/sse/filestorage/testsupport/AmazonS3TestSupport.java
... ...
@@ -2,14 +2,22 @@ package com.sap.sse.filestorage.testsupport;
2 2
3 3
import com.sap.sse.filestorage.InvalidPropertiesException;
4 4
import com.sap.sse.filestorage.impl.AmazonS3FileStorageServiceImpl;
5
+import com.sap.sse.security.SecurityService;
5 6
6 7
public class AmazonS3TestSupport {
7 8
public static final String s3AccessId = "AKIAJOX7PZ6ACI2FQU4A";
8 9
public static final String s3AccessKey = "NkijH2DfhWgb9fmESPjpeIbpUF+tC220KyTOfvGJ";
9 10
private static final String s3BucketName = "sapsailing-automatic-upload-test";
10 11
11
- public static AmazonS3FileStorageServiceImpl createService() throws InvalidPropertiesException {
12
- AmazonS3FileStorageServiceImpl service = new AmazonS3FileStorageServiceImpl();
12
+ public static AmazonS3FileStorageServiceImpl createService(final SecurityService securityService) throws InvalidPropertiesException {
13
+ AmazonS3FileStorageServiceImpl service = new AmazonS3FileStorageServiceImpl(/* bundleContext */ null) {
14
+ private static final long serialVersionUID = 6887160074291578082L;
15
+
16
+ @Override
17
+ protected SecurityService getSecurityService() {
18
+ return securityService;
19
+ }
20
+ };
13 21
service.internalSetProperty("accessId", s3AccessId);
14 22
service.internalSetProperty("accessKey", s3AccessKey);
15 23
service.internalSetProperty("bucketName", s3BucketName);
java/com.sap.sse.filestorage/src/com/sap/sse/filestorage/testsupport/DummyFileStorageService.java
... ...
@@ -21,7 +21,7 @@ public class DummyFileStorageService extends BaseFileStorageServiceImpl implemen
21 21
private static final long serialVersionUID = -3871744982404841496L;
22 22
23 23
public DummyFileStorageService() {
24
- super(NAME, "");
24
+ super(NAME, "", /* bundleContext */ null);
25 25
addProperties(property);
26 26
}
27 27
java/com.sap.sse.security.testsupport/.classpath
... ...
@@ -0,0 +1,7 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<classpath>
3
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
4
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
5
+ <classpathentry kind="src" path="src"/>
6
+ <classpathentry kind="output" path="bin"/>
7
+</classpath>
java/com.sap.sse.security.testsupport/.project
... ...
@@ -0,0 +1,28 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<projectDescription>
3
+ <name>com.sap.sse.security.testsupport</name>
4
+ <comment></comment>
5
+ <projects>
6
+ </projects>
7
+ <buildSpec>
8
+ <buildCommand>
9
+ <name>org.eclipse.jdt.core.javabuilder</name>
10
+ <arguments>
11
+ </arguments>
12
+ </buildCommand>
13
+ <buildCommand>
14
+ <name>org.eclipse.pde.ManifestBuilder</name>
15
+ <arguments>
16
+ </arguments>
17
+ </buildCommand>
18
+ <buildCommand>
19
+ <name>org.eclipse.pde.SchemaBuilder</name>
20
+ <arguments>
21
+ </arguments>
22
+ </buildCommand>
23
+ </buildSpec>
24
+ <natures>
25
+ <nature>org.eclipse.pde.PluginNature</nature>
26
+ <nature>org.eclipse.jdt.core.javanature</nature>
27
+ </natures>
28
+</projectDescription>
java/com.sap.sse.security.testsupport/.settings/org.eclipse.jdt.core.prefs
... ...
@@ -0,0 +1,7 @@
1
+eclipse.preferences.version=1
2
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
3
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
4
+org.eclipse.jdt.core.compiler.compliance=1.8
5
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
6
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
7
+org.eclipse.jdt.core.compiler.source=1.8
java/com.sap.sse.security.testsupport/.settings/org.eclipse.pde.core.prefs
... ...
@@ -0,0 +1,3 @@
1
+eclipse.preferences.version=1
2
+pluginProject.extensions=false
3
+resolve.requirebundle=false
java/com.sap.sse.security.testsupport/META-INF/MANIFEST.MF
... ...
@@ -0,0 +1,12 @@
1
+Manifest-Version: 1.0
2
+Bundle-ManifestVersion: 2
3
+Bundle-Name: Testsupport
4
+Bundle-SymbolicName: com.sap.sse.security.testsupport
5
+Bundle-Version: 1.0.0.qualifier
6
+Bundle-Vendor: SAP
7
+Automatic-Module-Name: com.sap.sse.security.testsupport
8
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
9
+Require-Bundle: com.sap.sse.security,
10
+ org.mockito.mockito-core;bundle-version="1.10.14",
11
+ com.sap.sse.common
12
+Export-Package: com.sap.sse.security.testsupport
java/com.sap.sse.security.testsupport/build.properties
... ...
@@ -0,0 +1,4 @@
1
+source.. = src/
2
+output.. = bin/
3
+bin.includes = META-INF/,\
4
+ .
java/com.sap.sse.security.testsupport/pom.xml
... ...
@@ -0,0 +1,12 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
3
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
4
+ <modelVersion>4.0.0</modelVersion>
5
+ <parent>
6
+ <artifactId>root</artifactId>
7
+ <groupId>com.sap.sailing</groupId>
8
+ <version>1.0.0-SNAPSHOT</version>
9
+ </parent>
10
+ <artifactId>com.sap.sse.security.testsupport</artifactId>
11
+ <packaging>eclipse-plugin</packaging>
12
+</project>
java/com.sap.sse.security.testsupport/src/com/sap/sse/security/testsupport/SecurityServiceMockFactory.java
... ...
@@ -0,0 +1,46 @@
1
+package com.sap.sse.security.testsupport;
2
+
3
+import java.util.UUID;
4
+import java.util.concurrent.Callable;
5
+
6
+import org.mockito.Mockito;
7
+import org.mockito.invocation.InvocationOnMock;
8
+import org.mockito.stubbing.Answer;
9
+
10
+import com.sap.sse.security.Action;
11
+import com.sap.sse.security.SecurityService;
12
+import com.sap.sse.security.shared.WithQualifiedObjectIdentifier;
13
+import com.sap.sse.security.shared.impl.UserGroupImpl;
14
+
15
+public class SecurityServiceMockFactory {
16
+ @SuppressWarnings("unchecked")
17
+ public static SecurityService mockSecurityService() {
18
+ UserGroupImpl defaultTenant = new UserGroupImpl(new UUID(0, 1), "defaultTenant");
19
+ final SecurityService result = Mockito.mock(SecurityService.class);
20
+ Mockito.doReturn(defaultTenant).when(result).getDefaultTenant();
21
+ Mockito.doAnswer(new Answer<Object>() {
22
+ @Override
23
+ public Object answer(InvocationOnMock invocation) throws Throwable {
24
+ return invocation.getArgumentAt(4, Callable.class).call();
25
+ }
26
+ }).when(result).setOwnershipCheckPermissionForObjectCreationAndRevertOnError(
27
+ Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any(Action.class));
28
+ Mockito.doAnswer(new Answer<Object>() {
29
+ @SuppressWarnings("rawtypes")
30
+ @Override
31
+ public Object answer(InvocationOnMock invocation) throws Throwable {
32
+ for (Object arg : invocation.getArguments()) {
33
+ if (arg instanceof Callable) {
34
+ return ((Callable) arg).call();
35
+ }
36
+ }
37
+ return null;
38
+ }
39
+ }).when(result).setOwnershipCheckPermissionForObjectCreationAndRevertOnError(Mockito.any(),
40
+ Mockito.any(), Mockito.any(), Mockito.any(Callable.class));
41
+ Mockito.doReturn(true).when(result)
42
+ .hasCurrentUserReadPermission(Mockito.any(WithQualifiedObjectIdentifier.class));
43
+ Mockito.doNothing().when(result).checkCurrentUserReadPermission(Mockito.any());
44
+ return result;
45
+ }
46
+}
java/pom.xml
... ...
@@ -174,6 +174,7 @@
174 174
<module>com.sap.sse.gwt.test</module>
175 175
<module>com.sap.sse.datamining.test</module>
176 176
<module>com.sap.sse.security.replication.test</module>
177
+ <module>com.sap.sse.security.testsupport</module>
177 178
<module>com.sap.sse.security.test</module>
178 179
<module>com.sap.sse.operationaltransformation.test</module>
179 180
<module>com.sap.sse.common.test</module>
wiki/info/security/permission-migration-tests.md
... ...
@@ -27,9 +27,11 @@ Any permissions directly or indirectly associated with the <all> user will be us
27 27
All pre existing users will receive the following additions:
28 28
29 29
* A group named by the user with suffix "-tenant" is created.
30
+* The new group owns itself; the user is the group's owning user.
30 31
* The user is a member of the newly created tenant group
31 32
* The user is the owner of itself and the associated group
32
-* The user has the role "user" qualified by the user itself but without a group qualification
33
+* The user has the role "user" qualified by the user itself
34
+* The user has another role "user" qualified by the newly created tenant group as a group qualification
33 35
34 36
### User called "admin"
35 37
... ...
@@ -51,14 +53,14 @@ There are several RoleDefinitions that are automatically created for new or migr
51 53
52 54
These roles are system roles that are intended to be used by any user. To ensure this, an ACL entry is generated for those roles granting action "READ" to the null group (all users).
53 55
54
-Most of those default RoleDefinitions also had role with the same name in the old role model (all but sailing_viewer). On existing servers, users having any old role, need to get an equivalent role associated. Any user having one of these old roles (excluding the "admin" case described below) will have the new version of this role qualified by the server's default group associated.
56
+Most of those default RoleDefinitions also had a role with the same name in the old role model (all but sailing_viewer). On existing servers, users having any old role need to get an equivalent role associated. Any user having one of these old roles (excluding the "admin" case described below) will have the new version of this role qualified by the server's default group associated.
55 57
This means those users should still have equivalent permissions but only for objects owned by the mentioned server group.
56 58
57 59
Any other role would be lost. This is most probably an unlikely case due to the fact that the old permission UI had no possibility to define new roles.
58 60
59 61
### Tenants
60 62
61
-Existing users (including the "admin" but excluding "<all>) will automatically get a UserGroup created named like the user with the suffix "-tenant". This means the admin's tenant is called "admin-tenant".
63
+Existing users (including the "admin" but excluding "<all>") will automatically get a UserGroup created named like the user with the suffix "-tenant". This means the admin's tenant is called "admin-tenant".
62 64
63 65
### Default creation tenant
64 66
... ...
@@ -80,7 +82,7 @@ Any security and domain object being loaded will receive an initial ownership. T
80 82
81 83
### ACLs
82 84
83
-The only ACLs that are automatically created on migration or server initialization are those to make the initial RoleDefinitions publicly readable. No other ACLs are intended to exist for new or initially migrated servers.
85
+The only ACLs that are automatically created on migration or server initialization are those to make the initial RoleDefinitions publicly readable. No other ACLs are intended to exist for new or initially migrated server.
84 86
85 87
### Users having specific permissions
86 88
wiki/info/security/security-end-user-docs.md