Skip to content

Commit

Permalink
make it thread safe
Browse files Browse the repository at this point in the history
  • Loading branch information
umjammer committed May 8, 2020
1 parent 0ee9d20 commit ba39cbb
Show file tree
Hide file tree
Showing 14 changed files with 300 additions and 214 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ $ git push heroku master && heroku logs -t
<dependency>
<groupId>com.github.umjammer</groupId>
<artifactId>vavi-apps-fuse</artifactId>
<version>0.0.8</version>
<version>0.0.9</version>
<exclusions>
<exclusion>
<groupId>org.apache.jackrabbit</groupId>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
/*
* Copyright (c) 2020 by Naohide Sano, All rights reserved.
*
* Programmed by Naohide Sano
*/

package org.cryptomator.webdav.core.filters;

import java.io.IOException;
Expand All @@ -11,6 +17,13 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
* WebdavForBrowserFilter.
*
* @author <a href="mailto:umjammer@gmail.com">Naohide Sano</a> (umjammer)
* @version 0.00 2020/05/08 umjammer initial version <br>
*/
public class WebdavForBrowserFilter implements HttpFilter {

private static final Logger LOG = LoggerFactory.getLogger(WebdavForBrowserFilter.class);
Expand Down
101 changes: 85 additions & 16 deletions src/main/java/vavi/apps/webdav/Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,13 @@

package vavi.apps.webdav;

import java.io.IOException;
import java.net.URI;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

import javax.sql.DataSource;

Expand All @@ -15,20 +21,27 @@
import org.cryptomator.webdav.core.filters.UnicodeResourcePathNormalizationFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.security.web.firewall.HttpFirewall;
import org.springframework.security.web.firewall.StrictHttpFirewall;

import com.github.fge.filesystem.box.provider.BoxFileSystemProvider;
import com.github.fge.fs.dropbox.provider.DropBoxFileSystemProvider;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;

import vavi.net.webdav.JavaFsWebDavServlet;
import vavi.net.webdav.SqlStrageDao;
import vavi.net.webdav.WebdavService;
import vavi.net.webdav.auth.StrageDao;
import vavi.net.webdav.auth.WebOAuth2;
import vavi.net.webdav.auth.WebUserCredential;
import vavi.net.webdav.auth.box.BoxWebAppCredential;
import vavi.net.webdav.auth.box.BoxWebOAuth2;
import vavi.net.webdav.auth.dropbox.DropBoxWebAppCredential;
Expand All @@ -37,6 +50,8 @@
import vavi.net.webdav.auth.google.GoogleWebAuthenticator;
import vavi.net.webdav.auth.microsoft.MicrosoftWebAppCredential;
import vavi.net.webdav.auth.microsoft.MicrosoftWebOAuth2;
import vavi.nio.file.googledrive.GoogleDriveFileSystemProvider;
import vavi.nio.file.onedrive4.OneDriveFileSystemProvider;


/**
Expand All @@ -46,8 +61,11 @@
* @version 0.00 2020/05/05 umjammer initial version <br>
*/
@Configuration
@ComponentScan("vavi.net.webdav")
public class Config {

// private static final Logger LOG = LoggerFactory.getLogger(Config.class);

@Value("${spring.datasource.url}")
private String dbUrl;

Expand Down Expand Up @@ -129,28 +147,79 @@ public DropBoxWebAppCredential dropboxAppCredential() {
}

@Bean
public MicrosoftWebOAuth2 microsoftWebOAuth2(@Autowired MicrosoftWebAppCredential microsoftAppCredential) {
return new MicrosoftWebOAuth2(microsoftAppCredential);
}

@Bean
public GoogleWebAuthenticator googleWebOAuth2(@Autowired GoogleWebAppCredential googleAppCredential) {
return new GoogleWebAuthenticator(googleAppCredential);
public WebdavService webdavService() {
return new WebdavService();
}

@Bean
public BoxWebOAuth2 boxWebOAuth2(@Autowired BoxWebAppCredential boxAppCredential) {
return new BoxWebOAuth2(boxAppCredential);
@Autowired
MicrosoftWebAppCredential microsoftAppCredential;
@Autowired
GoogleWebAppCredential googleAppCredential;
@Autowired
BoxWebAppCredential boxAppCredential;
@Autowired
DropBoxWebAppCredential dropboxAppCredential;

@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public WebOAuth2<?, ?> getWebOAuth2(String scheme) throws IOException {
switch (scheme) {
case "onedrive":
return new MicrosoftWebOAuth2(microsoftAppCredential);
case "googledrive":
return new GoogleWebAuthenticator(googleAppCredential);
case "box":
return new BoxWebOAuth2(boxAppCredential);
case "dropbox":
return new DropBoxWebOAuth2(dropboxAppCredential);
default:
throw new IllegalArgumentException("unsupported scheme: " + scheme);
}
}

/**
* @param id 'scheme:id' i.e. 'onedrive:foo@bar.com'
*/
@Bean
public DropBoxWebOAuth2 dropBoxWebOAuth2(@Autowired DropBoxWebAppCredential dropboxAppCredential) {
return new DropBoxWebOAuth2(dropboxAppCredential);
}
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public FileSystem getFileSystem(String id) throws IOException {
String[] part1s = id.split(":");
if (part1s.length < 2) {
throw new IllegalArgumentException("bad 2nd path component: should be 'scheme:id' i.e. 'onedrive:foo@bar.com'");
}
String scheme = part1s[0];
String idForScheme = part1s[1];

URI uri = URI.create(scheme + ":///");
Map<String, Object> env = new HashMap<>();
switch (scheme) {
case "onedrive":
env.put(OneDriveFileSystemProvider.ENV_APP_CREDENTIAL, microsoftAppCredential);
env.put(OneDriveFileSystemProvider.ENV_USER_CREDENTIAL, new WebUserCredential(idForScheme));
env.put("ignoreAppleDouble", true);
break;
case "googledrive":
env.put(GoogleDriveFileSystemProvider.ENV_APP_CREDENTIAL, googleAppCredential);
env.put(GoogleDriveFileSystemProvider.ENV_USER_CREDENTIAL, new WebUserCredential(idForScheme));
env.put("ignoreAppleDouble", true);
break;
case "box":
env.put(BoxFileSystemProvider.ENV_APP_CREDENTIAL, boxAppCredential);
env.put(BoxFileSystemProvider.ENV_USER_CREDENTIAL, new WebUserCredential(idForScheme));
env.put("ignoreAppleDouble", true);
break;
case "dropbox":
env.put(DropBoxFileSystemProvider.ENV_APP_CREDENTIAL, dropboxAppCredential);
env.put(DropBoxFileSystemProvider.ENV_USER_CREDENTIAL, new WebUserCredential(idForScheme));
env.put("ignoreAppleDouble", true);
break;
default:
throw new IllegalArgumentException("unsupported scheme: " + scheme);
}

@Bean
public WebdavService webdavService() {
return new WebdavService();
// https://github.com/spring-projects/spring-boot/issues/7110#issuecomment-252247036
FileSystem fs = FileSystems.newFileSystem(uri, env, Thread.currentThread().getContextClassLoader());
return fs;
}
}

Expand Down
8 changes: 4 additions & 4 deletions src/main/java/vavi/apps/webdav/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ String microsoft(Model model,
} else {
model.addAttribute("error", error);
model.addAttribute("errorDescription", errorDescription);
return "onedrive";
return "app_error";
}
}

Expand All @@ -103,7 +103,7 @@ String box(Model model,
} else {
model.addAttribute("error", error);
model.addAttribute("errorDescription", errorDescription);
return "onedrive";
return "app_error";
}
}

Expand All @@ -119,7 +119,7 @@ String dropbox(Model model,
} else {
model.addAttribute("error", error);
model.addAttribute("errorDescription", errorDescription);
return "onedrive";
return "app_error";
}
}

Expand All @@ -135,7 +135,7 @@ String google(Model model,
} else {
model.addAttribute("error", error);
model.addAttribute("errorDescription", errorDescription);
return "onedrive";
return "app_error";
}
}
}
11 changes: 11 additions & 0 deletions src/main/java/vavi/apps/webdav/SecurityConfig.java
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
/*
* Copyright (c) 2019 by Naohide Sano, All rights reserved.
*
* Programmed by Naohide Sano
*/

package vavi.apps.webdav;

Expand All @@ -10,6 +15,12 @@
import vavi.net.webdav.JavaFsWebDavServlet;


/**
* SecurityConfig.
*
* @author <a href="mailto:umjammer@gmail.com">Naohide Sano</a> (umjammer)
* @version 0.00 2020/05/08 umjammer initial version <br>
*/
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

Expand Down
65 changes: 65 additions & 0 deletions src/main/java/vavi/net/webdav/MyBeanFactory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* https://stackoverflow.com/questions/12537851/accessing-spring-beans-in-static-method
*/

package vavi.net.webdav;

import java.io.IOException;
import java.nio.file.FileSystem;

import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import vavi.net.webdav.auth.OAuthException;
import vavi.net.webdav.auth.WebOAuth2;


/**
* gather spring dependencies.
*
* @author <a href="mailto:umjammer@gmail.com">Naohide Sano</a> (umjammer)
* @version 0.00 2020/05/08 umjammer initial version <br>
*/
@Service
public class MyBeanFactory implements InitializingBean {
private static MyBeanFactory instance;

@Autowired
BeanFactory beanFactory;

private FileSystem getFileSystemInternal(String id) throws IOException {
try {
FileSystem fs = beanFactory.getBean(FileSystem.class, id);
return fs;
} catch (BeanCreationException e) {
OAuthException t = findRootCause(e, OAuthException.class);
throw t != null ? t : e;
}
}

private <T extends Throwable> T findRootCause(Throwable t, Class<T> clazz) {
while (t.getCause() != null) {
t = t.getCause();
if (clazz.isInstance(t)) {
return clazz.cast(t);
}
}
return null;
}

@Override
public void afterPropertiesSet() throws Exception {
instance = this;
}

public static FileSystem getFileSystem(String id) throws IOException {
return instance.getFileSystemInternal(id);
}

public static WebOAuth2<?, ?> getWebOAuth2(String scheme) {
return instance.beanFactory.getBean(WebOAuth2.class, scheme);
}
}
27 changes: 18 additions & 9 deletions src/main/java/vavi/net/webdav/SqlStrageDao.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

import javax.sql.DataSource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import vavi.net.webdav.auth.StrageDao;
Expand All @@ -30,7 +32,7 @@
*/
public class SqlStrageDao implements StrageDao {

// private static final Logger LOG = LoggerFactory.getLogger(PostgressStrageDao.class);
private static final Logger LOG = LoggerFactory.getLogger(SqlStrageDao.class);

@Autowired
private DataSource dataSource;
Expand All @@ -53,8 +55,10 @@ public List<String> load() {
@Override
public void update(String id, String token) {
try (Connection connection = dataSource.getConnection()) {
Statement stmt = connection.createStatement();
stmt.executeUpdate("UPDATE credential SET token = '" + token + "' WHERE id = '" + id + "'");
PreparedStatement pstmt = connection.prepareStatement("UPDATE credential SET token = ? WHERE id = ?");
pstmt.setString(1, token);
pstmt.setString(2, id);
pstmt.execute();
} catch (SQLException e) {
throw new IllegalStateException(e);
}
Expand All @@ -63,9 +67,11 @@ public void update(String id, String token) {
@Override
public String select(String id) {
try (Connection connection = dataSource.getConnection()) {
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery("SELECT token FROM credential WHERE id = '" + id + "'");
PreparedStatement pstmt = connection.prepareStatement("SELECT token FROM credential WHERE id = ?");
pstmt.setString(1, id);
ResultSet rs = pstmt.executeQuery();
if (rs.next()) {
LOG.debug("[" + id + "]: " + rs.getString("token"));
return rs.getString("token");
} else {
return null;
Expand All @@ -75,11 +81,14 @@ public String select(String id) {
}
}

private static final String googleId = "StoredCredential";

@Override
public byte[] selectGoogle() {
try (Connection connection = dataSource.getConnection()) {
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM google WHERE id = 'StoredCredential'");
PreparedStatement pstmt = connection.prepareStatement("SELECT * FROM google WHERE id = ?");
pstmt.setString(1, googleId);
ResultSet rs = pstmt.executeQuery();

if (rs.next()) {
return rs.getBytes("credentials");
Expand All @@ -94,9 +103,9 @@ public byte[] selectGoogle() {
public void updateGoogle(byte[] credentials) {
try (Connection connection = dataSource.getConnection()) {
connection.setAutoCommit(false);
PreparedStatement pstmt = connection
.prepareStatement("UPDATE google SET credentials = ? WHERE id = 'StoredCredential'");
PreparedStatement pstmt = connection.prepareStatement("UPDATE google SET credentials = ? WHERE id = ?");
pstmt.setBytes(1, credentials);
pstmt.setString(2, googleId);
pstmt.execute();
connection.commit();
} catch (SQLException e) {
Expand Down
Loading

0 comments on commit ba39cbb

Please sign in to comment.