-
-
Notifications
You must be signed in to change notification settings - Fork 166
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add classes for offline client caches
Update sqlite to support android. Comment out Java thumbnail generation which causes native image issues on android.
- Loading branch information
1 parent
ee1db70
commit 0d57959
Showing
21 changed files
with
497 additions
and
65 deletions.
There are no files selected for viewing
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package peergos.server; | ||
|
||
import peergos.shared.storage.auth.*; | ||
|
||
import java.util.*; | ||
import java.util.concurrent.*; | ||
|
||
public interface BatCache { | ||
|
||
CompletableFuture<List<BatWithId>> getUserBats(String username); | ||
|
||
CompletableFuture<Boolean> setUserBats(String username, List<BatWithId> bats); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package peergos.server; | ||
|
||
import peergos.shared.storage.*; | ||
import peergos.shared.util.*; | ||
|
||
import java.util.*; | ||
import java.util.concurrent.*; | ||
|
||
public class DirectOnlyStorage extends DelegatingStorage { | ||
private final ContentAddressedStorage target; | ||
|
||
public DirectOnlyStorage(ContentAddressedStorage target) { | ||
super(target); | ||
this.target = target; | ||
} | ||
|
||
@Override | ||
public ContentAddressedStorage directToOrigin() { | ||
return new DirectOnlyStorage(target.directToOrigin()); | ||
} | ||
|
||
@Override | ||
public CompletableFuture<BlockStoreProperties> blockStoreProperties() { | ||
return Futures.of(new BlockStoreProperties(false, false, false, Optional.empty(), Optional.empty())); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
package peergos.server; | ||
|
||
import peergos.server.sql.*; | ||
import peergos.server.util.Logging; | ||
import peergos.shared.cbor.*; | ||
import peergos.shared.corenode.*; | ||
import peergos.shared.crypto.hash.*; | ||
|
||
import java.sql.*; | ||
import java.util.*; | ||
import java.util.function.*; | ||
import java.util.logging.*; | ||
|
||
public class JdbcPkiCache { | ||
private static final Logger LOG = Logging.LOG(); | ||
|
||
private static final String CREATE = "INSERT INTO pkistate (username, chain, pubkey) VALUES(?, ?, ?)"; | ||
private static final String UPDATE = "UPDATE pkistate SET chain=?, pubkey=? WHERE username = ?"; | ||
private static final String GET_BY_USERNAME = "SELECT * FROM pkistate WHERE username = ? LIMIT 1;"; | ||
private static final String GET_BY_KEY = "SELECT * FROM pkistate WHERE pubkey = ? LIMIT 1;"; | ||
|
||
private volatile boolean isClosed; | ||
private Supplier<Connection> conn; | ||
|
||
public JdbcPkiCache(Supplier<Connection> conn, SqlSupplier commands) { | ||
this.conn = conn; | ||
init(commands); | ||
} | ||
|
||
private Connection getConnection() { | ||
Connection connection = conn.get(); | ||
try { | ||
connection.setAutoCommit(true); | ||
connection.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE); | ||
return connection; | ||
} catch (SQLException e) { | ||
throw new RuntimeException(e); | ||
} | ||
} | ||
|
||
private synchronized void init(SqlSupplier commands) { | ||
if (isClosed) | ||
return; | ||
|
||
try (Connection conn = getConnection()) { | ||
commands.createTable("CREATE TABLE IF NOT EXISTS pkistate " + | ||
"(username text primary key not null, chain text not null, pubkey text not null); " + | ||
"CREATE UNIQUE INDEX IF NOT EXISTS pkistate_index ON pkistate (username);", conn); | ||
} catch (Exception e) { | ||
throw new RuntimeException(e); | ||
} | ||
} | ||
|
||
private boolean hasUser(String username) { | ||
try (Connection conn = getConnection(); | ||
PreparedStatement present = conn.prepareStatement(GET_BY_USERNAME)) { | ||
conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE); | ||
present.setString(1, username); | ||
ResultSet rs = present.executeQuery(); | ||
if (rs.next()) { | ||
return true; | ||
} | ||
return false; | ||
} catch (SQLException sqe) { | ||
LOG.log(Level.WARNING, sqe.getMessage(), sqe); | ||
throw new RuntimeException(sqe); | ||
} | ||
} | ||
|
||
public List<UserPublicKeyLink> getChain(String username) { | ||
try (Connection conn = getConnection(); | ||
PreparedStatement present = conn.prepareStatement(GET_BY_USERNAME)) { | ||
conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE); | ||
present.setString(1, username); | ||
ResultSet rs = present.executeQuery(); | ||
if (rs.next()) { | ||
return ((CborObject.CborList)CborObject.fromByteArray(rs.getBytes("chain"))).map(UserPublicKeyLink::fromCbor); | ||
} | ||
throw new IllegalStateException("Unknown user " + username); | ||
} catch (SQLException sqe) { | ||
LOG.log(Level.WARNING, sqe.getMessage(), sqe); | ||
throw new RuntimeException(sqe); | ||
} | ||
} | ||
|
||
public boolean setChain(String username, List<UserPublicKeyLink> chain) { | ||
PublicKeyHash owner = chain.get(chain.size() - 1).owner; | ||
if (hasUser(username)) { | ||
try (Connection conn = getConnection(); | ||
PreparedStatement insert = conn.prepareStatement(UPDATE)) { | ||
conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE); | ||
|
||
insert.setBytes(1, new CborObject.CborList(chain).serialize()); | ||
insert.setString(2, new String(Base64.getEncoder().encode(owner.serialize()))); | ||
insert.setString(3, username); | ||
int changed = insert.executeUpdate(); | ||
return changed > 0; | ||
} catch (SQLException sqe) { | ||
LOG.log(Level.WARNING, sqe.getMessage(), sqe); | ||
return false; | ||
} | ||
} else { | ||
try (Connection conn = getConnection(); | ||
PreparedStatement stmt = conn.prepareStatement(CREATE)) { | ||
stmt.setString(1, username); | ||
stmt.setBytes(2, new CborObject.CborList(chain).serialize()); | ||
stmt.setString(3, new String(Base64.getEncoder().encode(owner.serialize()))); | ||
stmt.executeUpdate(); | ||
return true; | ||
} catch (SQLException sqe) { | ||
LOG.log(Level.WARNING, sqe.getMessage(), sqe); | ||
return false; | ||
} | ||
} | ||
} | ||
|
||
public String getUsername(PublicKeyHash identity) { | ||
try (Connection conn = getConnection(); | ||
PreparedStatement stmt = conn.prepareStatement(GET_BY_KEY)) { | ||
stmt.setString(1, new String(Base64.getEncoder().encode(identity.serialize()))); | ||
ResultSet rs = stmt.executeQuery(); | ||
if (rs.next()) { | ||
return rs.getString("username"); | ||
} | ||
|
||
throw new IllegalStateException("Unknown user identity key."); | ||
} catch (SQLException sqe) { | ||
LOG.log(Level.WARNING, sqe.getMessage(), sqe); | ||
throw new RuntimeException(sqe); | ||
} | ||
} | ||
|
||
public synchronized void close() { | ||
if (isClosed) | ||
return; | ||
|
||
isClosed = true; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package peergos.server; | ||
|
||
import peergos.server.login.*; | ||
import peergos.shared.crypto.asymmetric.*; | ||
import peergos.shared.user.*; | ||
|
||
import java.util.*; | ||
import java.util.concurrent.*; | ||
|
||
public class OfflineAccountStore implements Account { | ||
|
||
private final Account target; | ||
private final JdbcAccount local; | ||
|
||
public OfflineAccountStore(Account target, JdbcAccount local) { | ||
this.target = target; | ||
this.local = local; | ||
} | ||
|
||
@Override | ||
public CompletableFuture<Boolean> setLoginData(LoginData login, byte[] auth) { | ||
return target.setLoginData(login, auth).thenApply(r -> { | ||
if (r) | ||
local.setLoginData(login); | ||
return r; | ||
}); | ||
} | ||
|
||
@Override | ||
public CompletableFuture<UserStaticData> getLoginData(String username, PublicSigningKey authorisedReader, byte[] auth) { | ||
return target.getLoginData(username, authorisedReader, auth) | ||
.thenApply(entryPoints -> { | ||
local.setLoginData(new LoginData(username, entryPoints, authorisedReader, Optional.empty())); | ||
return entryPoints; | ||
}).exceptionally(t -> local.getEntryData(username, authorisedReader).join()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package peergos.server; | ||
|
||
import peergos.server.storage.auth.*; | ||
import peergos.shared.storage.auth.*; | ||
import peergos.shared.util.*; | ||
|
||
import java.util.*; | ||
import java.util.concurrent.*; | ||
|
||
public class OfflineBatCache implements BatCave { | ||
|
||
private final BatCave target; | ||
private final BatCache cache; | ||
|
||
public OfflineBatCache(BatCave target, BatCache cache) { | ||
this.target = target; | ||
this.cache = cache; | ||
} | ||
|
||
@Override | ||
public Optional<Bat> getBat(BatId id) { | ||
return target.getBat(id); | ||
} | ||
|
||
@Override | ||
public CompletableFuture<List<BatWithId>> getUserBats(String username, byte[] auth) { | ||
return Futures.asyncExceptionally( | ||
() -> target.getUserBats(username, auth).thenApply(bats -> { | ||
cache.setUserBats(username, bats); | ||
return bats; | ||
}), | ||
t -> cache.getUserBats(username)); | ||
} | ||
|
||
@Override | ||
public CompletableFuture<Boolean> addBat(String username, BatId id, Bat bat, byte[] auth) { | ||
return target.addBat(username, id, bat, auth); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
package peergos.server; | ||
|
||
import peergos.shared.corenode.*; | ||
import peergos.shared.crypto.*; | ||
import peergos.shared.crypto.hash.*; | ||
import peergos.shared.io.ipfs.multihash.*; | ||
import peergos.shared.storage.auth.*; | ||
import peergos.shared.user.*; | ||
|
||
import java.io.*; | ||
import java.util.*; | ||
import java.util.concurrent.*; | ||
|
||
public class OfflineCorenode implements CoreNode { | ||
|
||
private final CoreNode target; | ||
private final JdbcPkiCache pkiCache; | ||
|
||
public OfflineCorenode(CoreNode target, JdbcPkiCache pkiCache) { | ||
this.target = target; | ||
this.pkiCache = pkiCache; | ||
} | ||
|
||
@Override | ||
public CompletableFuture<Optional<RequiredDifficulty>> signup(String username, | ||
UserPublicKeyLink userPublicKeyLink, | ||
OpLog opLog, | ||
ProofOfWork proofOfWork, | ||
String token) { | ||
return target.signup(username, userPublicKeyLink, opLog, proofOfWork, token); | ||
} | ||
|
||
@Override | ||
public CompletableFuture<List<UserPublicKeyLink>> getChain(String username) { | ||
return target.getChain(username).thenApply(chain -> { | ||
pkiCache.setChain(username, chain); | ||
return chain; | ||
}).exceptionally(t -> pkiCache.getChain(username)); | ||
} | ||
|
||
@Override | ||
public CompletableFuture<Optional<RequiredDifficulty>> updateChain(String username, | ||
List<UserPublicKeyLink> chain, | ||
ProofOfWork proofOfWork, | ||
String token) { | ||
return target.updateChain(username, chain, proofOfWork, token) | ||
.thenApply(work -> { | ||
if (work.isEmpty()) | ||
pkiCache.setChain(username, target.getChain(username).join()); | ||
return work; | ||
}); | ||
} | ||
|
||
@Override | ||
public CompletableFuture<String> getUsername(PublicKeyHash identity) { | ||
return target.getUsername(identity) | ||
.exceptionally(t -> pkiCache.getUsername(identity)); | ||
} | ||
|
||
@Override | ||
public CompletableFuture<List<String>> getUsernames(String prefix) { | ||
return target.getUsernames(prefix) | ||
.exceptionally(t -> Collections.emptyList()); | ||
} | ||
|
||
@Override | ||
public CompletableFuture<UserSnapshot> migrateUser(String username, | ||
List<UserPublicKeyLink> newChain, | ||
Multihash currentStorageId, | ||
Optional<BatWithId> mirrorBat) { | ||
return target.migrateUser(username, newChain, currentStorageId, mirrorBat); | ||
} | ||
|
||
@Override | ||
public void close() throws IOException { | ||
target.close(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.