Files
openide/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnNativeClientAuthTest.java
Vladimir Krivosheev cf8cf718ce IJPL-158385 SvnFileUrlMappingImpl - pass scope to MergingUpdateQueue instead of Disposable
GitOrigin-RevId: c3e6fa4c42cd57c99fedad533410af4e4b7f66a4
2024-07-21 22:18:56 +00:00

562 lines
21 KiB
Java

// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.idea.svn;
import com.intellij.openapi.progress.EmptyProgressIndicator;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vcs.CheckoutProvider;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.VcsKey;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vcs.changes.CurrentContentRevision;
import com.intellij.openapi.vcs.update.UpdateSession;
import com.intellij.openapi.vcs.update.UpdatedFiles;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.vcsUtil.VcsUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.idea.svn.api.Depth;
import org.jetbrains.idea.svn.api.Revision;
import org.jetbrains.idea.svn.api.Url;
import org.jetbrains.idea.svn.auth.*;
import org.jetbrains.idea.svn.checkout.SvnCheckoutProvider;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeoutException;
import static com.intellij.testFramework.UsefulTestCase.assertExists;
import static org.jetbrains.idea.svn.SvnUtil.parseUrl;
import static org.junit.Assert.*;
@Ignore
public class SvnNativeClientAuthTest extends SvnTestCase {
private AcceptResult myCertificateAnswer = AcceptResult.ACCEPTED_TEMPORARILY;
private boolean myCredentialsCorrect = true;
private boolean mySaveCredentials = false;
private boolean myCancelAuth = false;
private static final String outHttpUser = "test";
private static final String outHttpPassword = "test";
private final static Url ourHTTP_URL = parseUrl("http://svnsrvtest/stuff/autoTest", false);
private final static Url ourHTTPS_URL = parseUrl("https://svnsrvtest:443/TestSSL/autoTest", false);
private int myCertificateAskedInteractivelyCount = 0;
private int myCredentialsAskedInteractivelyCount = 0;
private int myExpectedCreds = 0;
private int myExpectedCert = 0;
private boolean myIsSecure;
@Override
@Before
public void before() throws Exception {
super.before();
final File certFile = new File(myPluginRoot, getTestDataDir() + "/svn/____.pfx");
// replace authentication provider so that pass credentials without dialogs
final SvnConfiguration configuration = SvnConfiguration.getInstance(myProject);
final File svnconfig = FileUtil.createTempDirectory("svnconfig", "");
configuration.setConfigurationDirParameters(false, svnconfig.getPath());
final SvnAuthenticationManager interactiveManager = configuration.getInteractiveManager(vcs);
final SvnTestInteractiveAuthentication authentication = new SvnTestInteractiveAuthentication() {
@Override
public AcceptResult acceptServerAuthentication(Url url, String realm, Object certificate, boolean canCache) {
++ myCertificateAskedInteractivelyCount;
return myCertificateAnswer;
}
@Override
public AuthenticationData requestClientAuthentication(String kind, Url url, String realm, boolean canCache) {
if (myCancelAuth) return null;
return super.requestClientAuthentication(kind, url, realm, canCache);
}
};
interactiveManager.setAuthenticationProvider(authentication);
final SvnAuthenticationManager manager = configuration.getAuthenticationManager(vcs);
// will be the same as in interactive -> authentication notifier is not used
manager.setAuthenticationProvider(authentication);
authentication.addAuthentication(SvnAuthenticationManager.PASSWORD,
o -> {
++ myCredentialsAskedInteractivelyCount;
if (myCancelAuth) return null;
if (myCredentialsCorrect) {
return new PasswordAuthenticationData(outHttpUser, outHttpPassword, mySaveCredentials);
} else {
myCredentialsCorrect = true;// only once
return new PasswordAuthenticationData("1234214 23 4234", "324324", mySaveCredentials);
}
});
authentication.addAuthentication(SvnAuthenticationManager.SSL,
o -> {
++ myCredentialsAskedInteractivelyCount;
if (myCancelAuth) return null;
if (myCredentialsCorrect) {
return new CertificateAuthenticationData(certFile.getAbsolutePath(), "12345".toCharArray(),
mySaveCredentials);
} else {
myCredentialsCorrect = true;// only once
return new CertificateAuthenticationData("1232432423", "3245321532534235445".toCharArray(),
mySaveCredentials);
}
});
myCertificateAskedInteractivelyCount = 0;
myCredentialsAskedInteractivelyCount = 0;
}
@Test
public void testTmpHttpUpdate() throws Exception {
final File wc1 = testCheckoutImpl(ourHTTP_URL);
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
final SvnConfiguration instance = SvnConfiguration.getInstance(myProject);
clearAuthCache(instance);
mySaveCredentials = false;
updateSimple(wc1);
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
// credentials are cached now only
updateSimple(wc1);
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
}
@Test
public void testTmpSSLUpdate() throws Exception {
final File wc1 = testCheckoutImpl(ourHTTPS_URL);
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
//Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
final SvnConfiguration instance = SvnConfiguration.getInstance(myProject);
clearAuthCache(instance);
mySaveCredentials = false;
updateSimple(wc1);
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
//Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
// credentials are cached now only
updateSimple(wc1);
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
//Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
}
@Test
public void testPermanentSSLUpdate() throws Exception {
final File wc1 = testCheckoutImpl(ourHTTPS_URL);
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
//Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
final SvnConfiguration instance = SvnConfiguration.getInstance(myProject);
clearAuthCache(instance);
mySaveCredentials = true;
updateSimple(wc1);
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
//Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
// credentials are cached now only
updateSimple(wc1);
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
//Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
}
@Test
public void testPermanentHttpUpdate() throws Exception {
final File wc1 = testCheckoutImpl(ourHTTP_URL);
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
final SvnConfiguration instance = SvnConfiguration.getInstance(myProject);
clearAuthCache(instance);
mySaveCredentials = true;
updateSimple(wc1);
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
// credentials are cached now only
updateSimple(wc1);
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
}
@Test
public void testTmpHttpCommit() throws Exception {
final File wc1 = testCheckoutImpl(ourHTTP_URL);
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
final SvnConfiguration instance = SvnConfiguration.getInstance(myProject);
clearAuthCache(instance);
mySaveCredentials = false;
testCommitImpl(wc1);
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
// credentials are cached now only
testCommitImpl(wc1);
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
}
@Test
public void testTmpSSLCommit() throws Exception {
final File wc1 = testCheckoutImpl(ourHTTPS_URL);
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
//Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
final SvnConfiguration instance = SvnConfiguration.getInstance(myProject);
clearAuthCache(instance);
mySaveCredentials = false;
testCommitImpl(wc1);
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
//Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
// credentials are cached now only
testCommitImpl(wc1);
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
//Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
}
@Test
public void testPermanentSSLCommit() throws Exception {
final File wc1 = testCheckoutImpl(ourHTTPS_URL);
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
//Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
final SvnConfiguration instance = SvnConfiguration.getInstance(myProject);
clearAuthCache(instance);
mySaveCredentials = true;
testCommitImpl(wc1);
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
//Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
// credentials are cached now only
testCommitImpl(wc1);
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
//Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
}
@Test
public void test2PermanentSSLCommit() throws Exception {
final File wc1 = testCheckoutImpl(ourHTTPS_URL);
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
//Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
final SvnConfiguration instance = SvnConfiguration.getInstance(myProject);
clearAuthCache(instance);
mySaveCredentials = true;
myCertificateAnswer = AcceptResult.ACCEPTED_PERMANENTLY;
testCommitImpl(wc1);
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
//Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
// credentials are cached now only
testCommitImpl(wc1);
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
//Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
}
private static void clearAuthCache(@NotNull SvnConfiguration instance) {
SvnAuthenticationNotifier.clearAuthenticationDirectory(instance);
instance.clearRuntimeStorage();
}
@Test
public void testMixedSSLCommit() throws Exception {
final File wc1 = testCheckoutImpl(ourHTTPS_URL);
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
//Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
final SvnConfiguration instance = SvnConfiguration.getInstance(myProject);
clearAuthCache(instance);
mySaveCredentials = false;
myCertificateAnswer = AcceptResult.ACCEPTED_PERMANENTLY;
testCommitImpl(wc1);
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
//Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
// credentials are cached now only
testCommitImpl(wc1);
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
//Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
//------------
clearAuthCache(instance);
mySaveCredentials = true;
myCertificateAnswer = AcceptResult.ACCEPTED_TEMPORARILY;
testCommitImpl(wc1);
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
//Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
testCommitImpl(wc1);
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
//Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
}
@Test
public void testPermanentHttpCommit() throws Exception {
final File wc1 = testCheckoutImpl(ourHTTP_URL);
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
final SvnConfiguration instance = SvnConfiguration.getInstance(myProject);
clearAuthCache(instance);
mySaveCredentials = true;
testCommitImpl(wc1);
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
// credentials are cached now only
testCommitImpl(wc1);
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
}
@Test
public void testFailedThenSuccessTmpHttpUpdate() throws Exception {
final File wc1 = testCheckoutImpl(ourHTTP_URL);
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
final SvnConfiguration instance = SvnConfiguration.getInstance(myProject);
clearAuthCache(instance);
mySaveCredentials = false;
myCredentialsCorrect = false;
updateSimple(wc1);
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
// credentials are cached now only
updateSimple(wc1);
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
}
@Test
public void testFailedThenSuccessTmpSSLUpdate() throws Exception {
final File wc1 = testCheckoutImpl(ourHTTPS_URL);
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
//Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
final SvnConfiguration instance = SvnConfiguration.getInstance(myProject);
clearAuthCache(instance);
mySaveCredentials = false;
myCredentialsCorrect = false;
updateSimple(wc1);
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
// credentials wrong, but certificate was ok accepted
//Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
// credentials are cached now only
updateSimple(wc1);
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
//Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
}
@Test
public void testCertificateRejectedThenCredentialsFailedThenSuccessTmpSSLUpdate() throws Exception {
final File wc1 = testCheckoutImpl(ourHTTPS_URL);
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
//Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
final SvnConfiguration instance = SvnConfiguration.getInstance(myProject);
clearAuthCache(instance);
mySaveCredentials = false;
myCertificateAnswer = AcceptResult.REJECTED;
updateExpectAuthCanceled(wc1, "Authentication canceled");
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
//Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
myCertificateAnswer = AcceptResult.ACCEPTED_TEMPORARILY;
myCredentialsCorrect = false;
updateSimple(wc1);
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
// credentials wrong, but certificate was ok accepted
//Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
// credentials are cached now only
updateSimple(wc1);
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
//Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
}
@Test
public void testCanceledThenFailedThenSuccessTmpHttpUpdate() throws Exception {
final File wc1 = testCheckoutImpl(ourHTTP_URL);
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
final SvnConfiguration instance = SvnConfiguration.getInstance(myProject);
clearAuthCache(instance);
mySaveCredentials = false;
myCredentialsCorrect = false;
myCancelAuth = true;
updateExpectAuthCanceled(wc1, "Authentication canceled");
myCancelAuth = false;
updateSimple(wc1);
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
// credentials are cached now only
updateSimple(wc1);
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
}
@Test
public void testCanceledThenFailedThenSuccessTmpSSLUpdate() throws Exception {
final File wc1 = testCheckoutImpl(ourHTTPS_URL);
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
//Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
final SvnConfiguration instance = SvnConfiguration.getInstance(myProject);
clearAuthCache(instance);
mySaveCredentials = false;
myCredentialsCorrect = false;
myCancelAuth = true;
updateExpectAuthCanceled(wc1, "Authentication canceled");
myCancelAuth = false;
updateSimple(wc1);
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
//Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
// credentials are cached now only
updateSimple(wc1);
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
//Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
}
private File testCommitImpl(File wc1) throws IOException {
assertTrue(wc1.isDirectory());
final File file = FileUtil.createTempFile(wc1, "file", ".txt");
final VirtualFile vf = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file);
assertNotNull(vf);
final ArrayList<VirtualFile> files = new ArrayList<>();
files.add(vf);
final List<VcsException> exceptions = vcs.getCheckinEnvironment().scheduleUnversionedFilesForAddition(files);
assertTrue(exceptions.isEmpty());
final Change change = new Change(null, new CurrentContentRevision(VcsUtil.getFilePath(vf)));
commit(Collections.singletonList(change), "commit");
++ myExpectedCreds;
++ myExpectedCert;
return file;
}
private File testCheckoutImpl(@NotNull Url url) throws IOException, TimeoutException {
final File root = FileUtil.createTempDirectory("checkoutRoot", "");
root.deleteOnExit();
assertExists(root);
SvnCheckoutProvider
.checkout(myProject, root, url, Revision.HEAD, Depth.INFINITY, false, new CheckoutProvider.Listener() {
@Override
public void directoryCheckedOut(File directory, VcsKey vcs) {
}
@Override
public void checkoutCompleted() {
}
}, WorkingCopyFormat.ONE_DOT_SEVEN);
final int[] cnt = {0};
FileUtil.processFilesRecursively(root, file -> {
++ cnt[0];
return ! (cnt[0] > 1);
});
assertTrue(cnt[0] > 1);
myIsSecure = "https".equals(url.getProtocol());
if (myIsSecure) {
++ myExpectedCreds;
++ myExpectedCert;
}
vcsManager.setDirectoryMapping(root.getPath(), SvnVcs.VCS_NAME);
refreshSvnMappingsSynchronously();
return root;
}
private void updateExpectAuthCanceled(File wc1, String expectedText) {
assertTrue(wc1.isDirectory());
final VirtualFile vf = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(wc1);
final UpdatedFiles files = UpdatedFiles.create();
final UpdateSession session =
vcs.getUpdateEnvironment().updateDirectories(new FilePath[]{VcsUtil.getFilePath(vf)}, files, new EmptyProgressIndicator(),
new Ref<>());
assertTrue(session.getExceptions() != null && !session.getExceptions().isEmpty());
assertFalse(session.isCanceled());
assertTrue(session.getExceptions().get(0).getMessage().contains(expectedText));
if (myIsSecure) {
++ myExpectedCreds;
++ myExpectedCert;
}
}
private void updateSimple(File wc1) {
assertTrue(wc1.isDirectory());
final VirtualFile vf = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(wc1);
final UpdatedFiles files = UpdatedFiles.create();
final UpdateSession session =
vcs.getUpdateEnvironment().updateDirectories(new FilePath[]{VcsUtil.getFilePath(vf)}, files, new EmptyProgressIndicator(),
new Ref<>());
assertTrue(session.getExceptions().isEmpty());
assertFalse(session.isCanceled());
if (myIsSecure) {
++ myExpectedCreds;
++ myExpectedCert;
}
}
}