Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified scripts/initializr/common/src/main/resources/parley-modules.zip
Binary file not shown.
Binary file modified scripts/initializr/common/src/main/resources/savor-modules.zip
Binary file not shown.
Binary file not shown.
Binary file modified scripts/initializr/common/src/main/resources/wayline-modules.zip
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
*/
package com.codenameone.examples.parley;


import java.time.Instant;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
Expand All @@ -39,6 +39,17 @@ public static long number(Object value) {
return value instanceof Number ? ((Number) value).longValue() : 0L;
}

/// A timestamp column as epoch milliseconds. Anything but an `Instant`
/// means the query selected something other than a timestamp, which is
/// a bug to see rather than a zero to chart.
public static long millis(Object value) {
if (value instanceof Instant) {
return ((Instant) value).toEpochMilli();
}
throw new IllegalStateException("Expected a java.time.Instant column but got "
+ (value == null ? "null" : value.getClass().getName()));
}

/// A column as text; empty for null.
public static String text(Object value) {
return value == null ? "" : String.valueOf(value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import com.codenameone.examples.parley.repository.ReportRepository;

import java.io.IOException;
import java.time.Instant;
import java.util.List;

/// What closing an account does to the rows other parts of the server keep
Expand Down Expand Up @@ -118,7 +119,7 @@ public void removeEverythingOf(String username) throws IOException {
pushDevices.deleteByUsername(username);
// The other side of a live call holds a line too, and nothing else
// would ever free it once the call record is gone.
List<CallRecord> live = calls.liveOf(username);
List<CallRecord> live = calls.liveOf(username, Instant.EPOCH);
for (int iter = 0; iter < live.size(); iter++) {
lines.deleteByCallId(live.get(iter).getId());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import com.codenameone.examples.parley.repository.ProfileRepository;

import java.io.IOException;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
Expand Down Expand Up @@ -156,7 +157,7 @@ void create(String username, String password, String displayName, String phone,
profile.setDisplayName(displayName);
profile.setPhone(phone);
profile.setPhoneVerified(phoneVerified);
profile.setCreatedAt(openedAt);
profile.setCreatedAt(Instant.ofEpochMilli(openedAt));
profile.setLanguage("");
profiles.insert(profile);
}
Expand Down Expand Up @@ -393,7 +394,7 @@ private void retire(String username) throws IOException {
if (!closed.existsById(hash)) {
ClosedAccount row = new ClosedAccount();
row.setUsernameHash(hash);
row.setClosedAt(System.currentTimeMillis());
row.setClosedAt(Instant.now());
closed.insert(row);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import com.codenameone.examples.parley.repository.ModerationEventRepository;

import java.io.IOException;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;

Expand Down Expand Up @@ -58,8 +59,8 @@ public void record(String username, String by, String action, String reason)
// came with it -- would otherwise be listed in either order. The later
// one is stamped after the one before it, so the list is the order in
// which things were done.
Long newest = events.newest(username);
long after = newest == null ? 0L : newest.longValue() + 1L;
Instant newest = events.newest(username);
long after = newest == null ? 0L : newest.toEpochMilli() + 1L;
record(username, by, action, reason, Math.max(System.currentTimeMillis(), after));
}

Expand All @@ -72,7 +73,7 @@ public void record(String username, String by, String action, String reason, lon
ModerationEvent event = new ModerationEvent();
event.setId(Ids.next());
event.setUsername(username);
event.setCreatedAt(at);
event.setCreatedAt(Instant.ofEpochMilli(at));
event.setActor(by);
event.setAction(action);
event.setReason(why.length() > 255 ? why.substring(0, 255) : why);
Expand All @@ -86,7 +87,7 @@ public List<ModerationEventDto> events(String username) throws IOException {
List<ModerationEventDto> out = new ArrayList<ModerationEventDto>();
for (int iter = 0; iter < rows.size(); iter++) {
ModerationEvent row = rows.get(iter);
out.add(new ModerationEventDto(row.getCreatedAt(), row.getActor(), row.getAction(),
out.add(new ModerationEventDto(row.getCreatedAt().toEpochMilli(), row.getActor(), row.getAction(),
row.getReason()));
}
return out;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import com.codenameone.examples.parley.sms.SmsSender;

import java.io.IOException;
import java.time.Instant;

/// Proves an account's phone number by texting it a code.
///
Expand Down Expand Up @@ -72,7 +73,7 @@ public PhoneChallengeDto start(String username) throws IOException {
UserDto user = accounts.describe(username);
String code = newCode();
String codeHash = hash(username, code);
store(username, codeHash, System.currentTimeMillis());
store(username, codeHash, Instant.now());
try {
sms.send(user.phone(), "Your Parley code is " + code);
} catch (IOException failed) {
Expand All @@ -98,32 +99,32 @@ public PhoneChallengeDto start(String username) throws IOException {
/// one is kept, so at most two codes are live, and only one whose guesses
/// were not used up.
@Transactional
void store(String username, String codeHash, long now) throws IOException {
void store(String username, String codeHash, Instant now) throws IOException {
// Before the code is read: two requests for one account take turns,
// so the second finds the code the first just stored and is told to
// wait. Otherwise both pass the check below and both send a text.
accounts.hold(username);
PhoneCode pending = codes.findById(username);
if (pending != null && now - pending.getSentAt() < RESEND_SECONDS * 1000L) {
if (pending != null && pending.getSentAt().plusSeconds(RESEND_SECONDS).isAfter(now)) {
throw new ResponseStatusException(429, "Wait a moment before asking for another code");
}
boolean first = pending == null;
if (first) {
pending = new PhoneCode();
pending.setUsername(username);
} else if (pending.getExpiresAt() >= now && pending.getAttempts() < MAX_ATTEMPTS) {
} else if (!pending.getExpiresAt().isBefore(now) && pending.getAttempts() < MAX_ATTEMPTS) {
// With the guesses it has used: asking for another code must not
// buy the old one a fresh set.
pending.setPreviousHash(pending.getCodeHash());
pending.setPreviousExpiresAt(pending.getExpiresAt());
pending.setPreviousAttempts(pending.getAttempts());
} else {
pending.setPreviousHash("");
pending.setPreviousExpiresAt(0L);
pending.setPreviousExpiresAt(Instant.EPOCH);
pending.setPreviousAttempts(0);
}
pending.setCodeHash(codeHash);
pending.setExpiresAt(now + CODE_SECONDS * 1000L);
pending.setExpiresAt(now.plusSeconds(CODE_SECONDS));
pending.setAttempts(0);
pending.setSentAt(now);
if (first) {
Expand All @@ -148,17 +149,17 @@ void discard(String username, String codeHash) throws IOException {
return;
}
if (pending.getPreviousHash().length() == 0
|| pending.getPreviousExpiresAt() < System.currentTimeMillis()) {
|| pending.getPreviousExpiresAt().isBefore(Instant.now())) {
codes.deleteById(username);
return;
}
pending.setCodeHash(pending.getPreviousHash());
pending.setExpiresAt(pending.getPreviousExpiresAt());
pending.setAttempts(pending.getPreviousAttempts());
pending.setPreviousHash("");
pending.setPreviousExpiresAt(0L);
pending.setPreviousExpiresAt(Instant.EPOCH);
pending.setPreviousAttempts(0);
pending.setSentAt(0L);
pending.setSentAt(Instant.EPOCH);
}

/// Checks the code the user typed. Answers 400 for a wrong or expired one
Expand Down Expand Up @@ -186,7 +187,7 @@ boolean guess(String username, String code) throws IOException {
// row the other has.
accounts.hold(username);
PhoneCode pending = codes.findById(username);
if (pending == null || pending.getExpiresAt() < System.currentTimeMillis()) {
if (pending == null || pending.getExpiresAt().isBefore(Instant.now())) {
throw new ResponseStatusException(400, "That code has expired. Ask for a new one");
}
if (pending.getAttempts() >= MAX_ATTEMPTS) {
Expand Down Expand Up @@ -222,7 +223,7 @@ boolean guess(String username, String code) throws IOException {
boolean previous = Crypto.equalsConstantTime(given,
pending.getPreviousHash().getBytes("UTF-8"))
&& pending.getPreviousHash().length() > 0
&& pending.getPreviousExpiresAt() >= System.currentTimeMillis()
&& !pending.getPreviousExpiresAt().isBefore(Instant.now())
&& counted != null && counted.getPreviousAttempts() <= MAX_ATTEMPTS;
if (!current && !previous) {
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import com.codenameone.examples.parley.repository.ReportRepository;

import java.io.IOException;
import java.time.Instant;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
Expand Down Expand Up @@ -93,8 +94,8 @@ public AdminStatsDto dashboard() throws IOException {
(int) conversations.count(),
(int) (conversations.countByKind(Conversations.GROUP)
+ conversations.countByKind(Conversations.CHANNEL)),
(int) messages.countBySentAtGreaterThanEqual(today),
(int) calls.countByStartedAtGreaterThanEqual(today),
(int) messages.countBySentAtGreaterThanEqual(Instant.ofEpochMilli(today)),
(int) calls.countByStartedAtGreaterThanEqual(Instant.ofEpochMilli(today)),
(int) reports.countByStatus(OPEN), (int) bridges.count());
}

Expand All @@ -113,23 +114,23 @@ public StatsSeriesDto series(int days) throws IOException {
active.add(new HashSet<>());
}
int[] byHour = new int[24];
for (Object[] row : messages.since(since)) {
long at = Rows.number(row[0]);
for (Object[] row : messages.since(Instant.ofEpochMilli(since))) {
long at = Rows.millis(row[0]);
byHour[(int) (at % Days.MILLIS / 3600000L)]++;
int index = index(at, since, span);
if (index >= 0) {
dayMessages[index]++;
active.get(index).add(Rows.text(row[1]));
}
}
for (Long at : calls.startedSince(since)) {
int index = index(Rows.number(at), since, span);
for (Instant at : calls.startedSince(Instant.ofEpochMilli(since))) {
int index = index(Rows.millis(at), since, span);
if (index >= 0) {
dayCalls[index]++;
}
}
for (Long at : profiles.signUps(since)) {
int index = index(Rows.number(at), since, span);
for (Instant at : profiles.signUps(Instant.ofEpochMilli(since))) {
int index = index(Rows.millis(at), since, span);
if (index >= 0) {
dayUsers[index]++;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import com.codenameone.examples.parley.repository.MembershipRepository;

import java.io.IOException;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;

Expand Down Expand Up @@ -134,7 +135,7 @@ public BridgeLinkDto link(String username, BridgeRequestDto request) throws IOEx
link.setExternalChat(chat);
link.setLabel(Text.optional(request.label(), 80, "the link's name"));
link.setCreatedBy(username);
link.setCreatedAt(System.currentTimeMillis());
link.setCreatedAt(Instant.now());
links.save(link);
conversations.announce(row.getId(), "This conversation is now bridged to "
+ name(bridge.network()) + ". Messages here are no longer end-to-end encrypted.");
Expand Down Expand Up @@ -174,8 +175,8 @@ public void incoming(String network, String externalChat, String senderName, Str
return;
}
long now = System.currentTimeMillis();
events.deleteByReceivedAtLessThan(now - EVENT_MEMORY_MILLIS);
events.insert(new BridgeEvent(key, now));
events.deleteByReceivedAtLessThan(Instant.ofEpochMilli(now - EVENT_MEMORY_MILLIS));
events.insert(new BridgeEvent(key, Instant.ofEpochMilli(now)));
}
BridgeLink link = links.findByNetworkAndExternalChat(network, externalChat);
if (link == null) {
Expand Down Expand Up @@ -232,6 +233,6 @@ static String name(String network) {

static BridgeLinkDto toDto(BridgeLink row) {
return new BridgeLinkDto(row.getId(), row.getConversationId(), row.getNetwork(),
row.getExternalChat(), row.getLabel(), row.getCreatedAt());
row.getExternalChat(), row.getLabel(), row.getCreatedAt().toEpochMilli());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
Expand Down Expand Up @@ -173,11 +174,11 @@ public CallDto start(String username, CallStartDto request, boolean busy) throws
row.setCallee(callee);
row.setCalleeDevice("");
row.setVideo(request.video());
row.setStartedAt(now);
row.setStartedAt(Instant.ofEpochMilli(now));
boolean blocked = blocked(username, callee);
if (busy || lines.findById(callee) != null) {
row.setState(BUSY);
row.setEndedAt(now);
row.setEndedAt(Instant.ofEpochMilli(now));
} else {
row.setState(RINGING);
}
Expand Down Expand Up @@ -235,7 +236,7 @@ public void ring(CallDto call) throws IOException {
/// where it learns who is calling and that the call is still live.
@Transactional(readOnly = true)
public void ringDevice(String username, String device) throws IOException {
for (CallRecord row : calls.liveOf(username)) {
for (CallRecord row : calls.liveOf(username, Instant.EPOCH)) {
if (username.equals(row.getCallee()) && RINGING.equals(row.getState())
&& !blocked(row.getCaller(), row.getCallee())) {
live.toDevice(device, frame(row, "ring"));
Expand All @@ -262,7 +263,7 @@ public CallDto signal(String username, String id, CallSignalDto signal) throws I
if (signal.payload() != null && signal.payload().length() > MAX_PAYLOAD) {
throw new ResponseStatusException(413, "That signal is too long");
}
if (row.getEndedAt() != 0) {
if (!row.getEndedAt().equals(Instant.EPOCH)) {
// A late candidate for a call that is over is not an error the
// app can do anything about.
return toDto(row);
Expand Down Expand Up @@ -291,7 +292,7 @@ public CallDto signal(String username, String id, CallSignalDto signal) throws I
remember(row, signal.payload(), false);
} else if (ACCEPT.equals(type) && !caller && RINGING.equals(row.getState())) {
row.setState(ACCEPTED);
row.setAnsweredAt(now);
row.setAnsweredAt(Instant.ofEpochMilli(now));
row.setCalleeDevice(device);
// The callee's other devices are still ringing.
String ringId = uuid(row.getId());
Expand Down Expand Up @@ -377,14 +378,14 @@ public IceConfigDto ice(String username) {
@Transactional(rollbackFor = IOException.class)
public void reap() throws IOException {
long now = System.currentTimeMillis();
for (CallRecord row : calls.openSince(now - RING_MILLIS)) {
for (CallRecord row : calls.openSince(Instant.ofEpochMilli(now - RING_MILLIS), Instant.EPOCH)) {
if (RINGING.equals(row.getState())) {
end(row, MISSED, now);
Map<String, Object> frame = frame(row, "signal");
List<String> to = blocked(row.getCaller(), row.getCallee())
? Arrays.asList(row.getCaller()) : Arrays.asList(row.getCaller(), row.getCallee());
afterCommit(() -> live.toUsers(to, frame));
} else if (row.getAnsweredAt() < now - STALE_MILLIS) {
} else if (row.getAnsweredAt().toEpochMilli() < now - STALE_MILLIS) {
end(row, ENDED, now);
// Both apps still hold the call; without this they keep it
// open and turn every later call away as busy.
Expand Down Expand Up @@ -449,7 +450,7 @@ private Map<String, Object> replayed(CallRecord row, String type, String payload
private void end(CallRecord row, String state, long now) {
boolean ringing = RINGING.equals(row.getState());
row.setState(state);
row.setEndedAt(now);
row.setEndedAt(Instant.ofEpochMilli(now));
lines.deleteByCallId(row.getId());
if (setups.findById(row.getId()) != null) {
setups.deleteById(row.getId());
Expand Down Expand Up @@ -548,7 +549,7 @@ private static List<String> split(String urls) {

static CallDto toDto(CallRecord row) {
return new CallDto(row.getId(), row.getConversationId(), row.getCaller(),
row.getCallee(), row.isVideo(), row.getState(), row.getStartedAt(),
row.getAnsweredAt(), row.getEndedAt(), uuid(row.getId()));
row.getCallee(), row.isVideo(), row.getState(), row.getStartedAt().toEpochMilli(),
row.getAnsweredAt().toEpochMilli(), row.getEndedAt().toEpochMilli(), uuid(row.getId()));
}
}
Loading
Loading