diff --git a/src/main/java/im/rosetta/database/entity/Device.java b/src/main/java/im/rosetta/database/entity/Device.java index b3aa270..ee2f062 100644 --- a/src/main/java/im/rosetta/database/entity/Device.java +++ b/src/main/java/im/rosetta/database/entity/Device.java @@ -1,40 +1,51 @@ package im.rosetta.database.entity; -import im.rosetta.database.CreateUpdateEntity; +import java.util.ArrayList; +import java.util.List; +import im.rosetta.database.CreateUpdateEntity; +import jakarta.persistence.CascadeType; import jakarta.persistence.Column; import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.Index; +import jakarta.persistence.OneToMany; import jakarta.persistence.Table; @Entity @Table(name = "devices", indexes = { @Index(name = "idx_public_key", columnList = "publicKey, deviceId", unique = true) }) - public class Device extends CreateUpdateEntity { @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) + @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(name = "publicKey", nullable = false) private String publicKey; + @Column(name = "deviceId", nullable = false) private String deviceId; + @Column(name = "deviceName", nullable = false) private String deviceName; + @Column(name = "deviceOs", nullable = false) private String deviceOs; + /** * Время завершения сессии устройства */ @Column(name = "syncTime", nullable = true, columnDefinition = "bigint default 0") private Long syncTime; + @OneToMany(mappedBy = "device", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY) + private List tokens = new ArrayList<>(); + public Long getId() { return id; } @@ -59,6 +70,10 @@ public class Device extends CreateUpdateEntity { return syncTime; } + public List getTokens() { + return tokens; + } + public void setSyncTime(Long syncTime) { this.syncTime = syncTime; } @@ -79,4 +94,24 @@ public class Device extends CreateUpdateEntity { this.deviceOs = deviceOs; } -} + public void setTokens(List tokens) { + this.tokens = tokens; + } + + public void addToken(PushToken token) { + if (token == null) { + return; + } + this.tokens.add(token); + token.setDevice(this); + } + + public void removeToken(PushToken token) { + if (token == null) { + return; + } + this.tokens.remove(token); + token.setDevice(null); + } + +} \ No newline at end of file diff --git a/src/main/java/im/rosetta/database/entity/PushToken.java b/src/main/java/im/rosetta/database/entity/PushToken.java new file mode 100644 index 0000000..7a102a2 --- /dev/null +++ b/src/main/java/im/rosetta/database/entity/PushToken.java @@ -0,0 +1,85 @@ +package im.rosetta.database.entity; + +import im.rosetta.database.CreateUpdateEntity; +import im.rosetta.packet.runtime.TokenType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Index; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; + +@Entity +@Table( + name = "device_tokens", + uniqueConstraints = { + @UniqueConstraint(name = "uq_device_token", columnNames = {"device_id", "type", "token"}) + }, + indexes = { + @Index(name = "idx_device_token_type", columnList = "type"), + @Index(name = "idx_device_token_token", columnList = "token") + } +) +public class PushToken extends CreateUpdateEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(optional = false, fetch = FetchType.LAZY) + @JoinColumn(name = "device_id", nullable = false) + private Device device; + + @Enumerated(EnumType.STRING) + @Column(name = "type", nullable = false, length = 32) + private TokenType type; + + @Column(name = "token", nullable = false, columnDefinition = "TEXT") + private String token; + + public Long getId() { + return id; + } + + public Device getDevice() { + return device; + } + + public TokenType getType() { + return type; + } + + public String getToken() { + return token; + } + + public void setDevice(Device device) { + this.device = device; + } + + public void setType(TokenType type) { + this.type = type; + } + + public void setToken(String token) { + this.token = token; + } + + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + PushToken pushToken = (PushToken) o; + + if (!device.equals(pushToken.device)) return false; + if (type != pushToken.type) return false; + return token.equals(pushToken.token); + } +} \ No newline at end of file diff --git a/src/main/java/im/rosetta/database/entity/User.java b/src/main/java/im/rosetta/database/entity/User.java index aea18a2..3f3d2be 100644 --- a/src/main/java/im/rosetta/database/entity/User.java +++ b/src/main/java/im/rosetta/database/entity/User.java @@ -1,10 +1,8 @@ package im.rosetta.database.entity; import im.rosetta.database.CreateUpdateEntity; -import im.rosetta.database.converters.StringListConverter; import jakarta.persistence.Column; -import jakarta.persistence.Convert; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; @@ -12,9 +10,6 @@ import jakarta.persistence.Id; import jakarta.persistence.Index; import jakarta.persistence.Table; -import java.util.ArrayList; -import java.util.List; - @Entity @Table(name = "users", indexes = { @Index(name = "idx_users_publickey", columnList = "publicKey", unique = true) @@ -40,10 +35,6 @@ public class User extends CreateUpdateEntity { @Column(name = "publicKey", nullable = false, unique = true) private String publicKey; - @Convert(converter = StringListConverter.class) - @Column(name = "notificationsTokens", nullable = false, columnDefinition = "TEXT") - private List notificationsTokens = new ArrayList<>(); - public Long getId() { return id; @@ -89,12 +80,4 @@ public class User extends CreateUpdateEntity { this.verified = verified; } - public List getNotificationsTokens() { - return notificationsTokens; - } - - public void setNotificationsTokens(List notificationsTokens) { - this.notificationsTokens = notificationsTokens; - } - } diff --git a/src/main/java/im/rosetta/executors/Executor16PushNotification.java b/src/main/java/im/rosetta/executors/Executor16PushNotification.java index 370c846..a7c0f1c 100644 --- a/src/main/java/im/rosetta/executors/Executor16PushNotification.java +++ b/src/main/java/im/rosetta/executors/Executor16PushNotification.java @@ -1,11 +1,15 @@ package im.rosetta.executors; +import java.util.List; + import im.rosetta.Failures; import im.rosetta.client.tags.ECIAuthentificate; -import im.rosetta.database.entity.User; -import im.rosetta.database.repository.UserRepository; +import im.rosetta.database.entity.Device; +import im.rosetta.database.entity.PushToken; +import im.rosetta.database.repository.DeviceRepository; import im.rosetta.packet.Packet16PushNotification; -import im.rosetta.service.services.UserService; +import im.rosetta.packet.runtime.NetworkNotificationAction; +import im.rosetta.service.services.DeviceService; import io.orprotocol.ProtocolException; import io.orprotocol.client.Client; @@ -13,8 +17,8 @@ import io.orprotocol.packet.PacketExecutor; public class Executor16PushNotification extends PacketExecutor { - private final UserRepository userRepository = new UserRepository(); - private final UserService userService = new UserService(userRepository); + private final DeviceRepository deviceRepository = new DeviceRepository(); + private final DeviceService deviceService = new DeviceService(deviceRepository); @Override public void onPacketReceived(Packet16PushNotification packet, Client client) throws Exception, ProtocolException { @@ -33,15 +37,62 @@ public class Executor16PushNotification extends PacketExecutor tokens = device.getTokens(); + for(PushToken pushToken : tokens){ + if(pushToken.getToken().equals(token)){ + return pushToken; + } + } + return null; + } + + private Device findDevice(String publicKey, String deviceId) { + List devices = this.deviceService.getDevicesByPK(publicKey); + if(devices.size() == 0){ + /** + * У пользователя нет устройств, значит текущее устройство верифицировано + * такого быть не может, это избыточная проверка + */ + return null; + } + for(Device device : devices){ + if(device.getDeviceId().equals(deviceId)){ + return device; + } + } + return null; + } + } diff --git a/src/main/java/im/rosetta/packet/Packet16PushNotification.java b/src/main/java/im/rosetta/packet/Packet16PushNotification.java index 02a6ba4..52902a5 100644 --- a/src/main/java/im/rosetta/packet/Packet16PushNotification.java +++ b/src/main/java/im/rosetta/packet/Packet16PushNotification.java @@ -1,7 +1,7 @@ package im.rosetta.packet; import im.rosetta.packet.runtime.NetworkNotificationAction; - +import im.rosetta.packet.runtime.TokenType; import io.orprotocol.Stream; import io.orprotocol.packet.Packet; @@ -12,11 +12,15 @@ public class Packet16PushNotification extends Packet { private String notificationToken; private NetworkNotificationAction action; + private TokenType tokenType; + private String deviceId; @Override public void read(Stream stream) { this.notificationToken = stream.readString(); this.action = NetworkNotificationAction.fromCode(stream.readInt8()); + this.tokenType = TokenType.fromCode(stream.readInt8()); + this.deviceId = stream.readString(); } @Override @@ -25,6 +29,8 @@ public class Packet16PushNotification extends Packet { stream.writeInt16(this.packetId); stream.writeString(notificationToken); stream.writeInt8(action.getCode()); + stream.writeInt8(tokenType.getCode()); + stream.writeString(deviceId); return stream; } @@ -60,4 +66,36 @@ public class Packet16PushNotification extends Packet { this.action = action; } -} + /** + * Устанавливает тип токена пуш уведомлений. + * @param tokenType тип токена пуш уведомлений + */ + public void setTokenType(TokenType tokenType) { + this.tokenType = tokenType; + } + + /** + * Получить тип токена пуш уведомлений, который нужно подписать или отписать в зависимости от action + * @return тип токена пуш уведомлений + */ + public TokenType getTokenType() { + return tokenType; + } + + /** + * Девайс которому принадлежит токен пуш уведомлений, который нужно подписать или отписать в зависимости от action + * @return + */ + public String getDeviceId() { + return deviceId; + } + + /** + * Устанавливает девайс которому принадлежит токен пуш уведомлений, который нужно подписать или отписать в зависимости от action + * @param deviceId девайс которому принадлежит токен пуш уведомлений + */ + public void setDeviceId(String deviceId) { + this.deviceId = deviceId; + } + +} \ No newline at end of file diff --git a/src/main/java/im/rosetta/packet/runtime/README.md b/src/main/java/im/rosetta/packet/runtime/README.md new file mode 100644 index 0000000..6764a75 --- /dev/null +++ b/src/main/java/im/rosetta/packet/runtime/README.md @@ -0,0 +1,3 @@ +## Именование + +Если в названии класса есть слово Network значит этот тип используется только при сетевых передачах, если слова Network в названии класса нет значит он используется где-то кроме сетевых передач. \ No newline at end of file diff --git a/src/main/java/im/rosetta/packet/runtime/TokenType.java b/src/main/java/im/rosetta/packet/runtime/TokenType.java new file mode 100644 index 0000000..6d652a2 --- /dev/null +++ b/src/main/java/im/rosetta/packet/runtime/TokenType.java @@ -0,0 +1,34 @@ +package im.rosetta.packet.runtime; + +/** + * Тип токена для пуш уведомлений. Используется в Packet16PushNotification для указания типа токена, который нужно подписать/отписать. + */ +public enum TokenType { + /** + * FCM токен для пуш уведомлений, используется и iOS и Android + */ + FCM(0), + /** + * VoIP токен для пуш уведомлений, используется только на iOS для VoIP уведомлений + */ + VoIPApns(1); + + private int code; + + TokenType(int code){ + this.code = code; + } + + public int getCode() { + return code; + } + + public static TokenType fromCode(int code) { + for (TokenType type : values()) { + if (type.code == code) { + return type; + } + } + throw new IllegalArgumentException("Unknown NetworkTokenType code: " + code); + } +} diff --git a/src/main/java/im/rosetta/service/dispatch/MessageDispatcher.java b/src/main/java/im/rosetta/service/dispatch/MessageDispatcher.java index ae99e73..9440843 100644 --- a/src/main/java/im/rosetta/service/dispatch/MessageDispatcher.java +++ b/src/main/java/im/rosetta/service/dispatch/MessageDispatcher.java @@ -12,6 +12,7 @@ import im.rosetta.database.repository.UserRepository; import im.rosetta.packet.Packet11Typeing; import im.rosetta.packet.Packet7Read; import im.rosetta.packet.base.PacketBaseDialog; +import im.rosetta.service.dispatch.push.PushNotifyDispatcher; import im.rosetta.service.dispatch.runtime.PushType; import im.rosetta.service.services.BufferService; import im.rosetta.service.services.UserService; @@ -32,7 +33,7 @@ public class MessageDispatcher { private final ClientManager clientManager; private final BufferRepository bufferRepository = new BufferRepository(); private final BufferService bufferService; - private final FirebaseDispatcher firebaseDispatcher = new FirebaseDispatcher(); + private final PushNotifyDispatcher pushNotifyDispatcher = new PushNotifyDispatcher(); private final UserRepository userRepository = new UserRepository(); private final UserService userService = new UserService(userRepository); @@ -103,7 +104,7 @@ public class MessageDispatcher { * Если это пакет прочтения, то отправляем тихий пуш, что диалог прочитан, отправляем тому, кто читает диалог, чтобы * клиент мог очистить пуши для этого диалога */ - this.firebaseDispatcher.sendPushNotification(fromPublicKey, new HashMap<>(){ + this.pushNotifyDispatcher.sendPush(fromPublicKey, new HashMap<>(){ { put("type", PushType.READ); put("dialog", toPublicKey); @@ -114,7 +115,7 @@ public class MessageDispatcher { /** * Отправляем PUSH уведомление */ - this.firebaseDispatcher.sendPushNotification(groupMembersPublicKeys, new HashMap<>(){ + this.pushNotifyDispatcher.sendPush(groupMembersPublicKeys, new HashMap<>(){ { put("type", PushType.GROUP_MESSAGE); put("dialog", toPublicKey.replace("#group:", "")); @@ -173,7 +174,7 @@ public class MessageDispatcher { * Если это пакет прочтения, то отправляем тихий пуш, что диалог прочитан, отправляем тому, кто читает диалог, чтобы * клиент мог очистить пуши для этого диалога */ - this.firebaseDispatcher.sendPushNotification(fromPublicKey, new HashMap<>(){ + this.pushNotifyDispatcher.sendPush(fromPublicKey, new HashMap<>(){ { put("type", PushType.READ); put("dialog", toPublicKey); @@ -185,7 +186,7 @@ public class MessageDispatcher { /** * Отправляем PUSH уведомление получателю */ - this.firebaseDispatcher.sendPushNotification(toPublicKey, new HashMap<>(){ + this.pushNotifyDispatcher.sendPush(toPublicKey, new HashMap<>(){ { put("type", PushType.PERSONAL_MESSAGE); put("dialog", fromPublicKey); diff --git a/src/main/java/im/rosetta/service/dispatch/push/PushNotifyDispatcher.java b/src/main/java/im/rosetta/service/dispatch/push/PushNotifyDispatcher.java new file mode 100644 index 0000000..44c994d --- /dev/null +++ b/src/main/java/im/rosetta/service/dispatch/push/PushNotifyDispatcher.java @@ -0,0 +1,78 @@ +package im.rosetta.service.dispatch.push; + +import java.util.HashMap; +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import im.rosetta.database.entity.Device; +import im.rosetta.database.entity.PushToken; +import im.rosetta.database.repository.DeviceRepository; +import im.rosetta.packet.runtime.TokenType; +import im.rosetta.service.dispatch.push.dispatchers.FCM; +import im.rosetta.service.dispatch.push.dispatchers.VoIPApns; +import im.rosetta.service.services.DeviceService; + +public class PushNotifyDispatcher { + + private DeviceRepository deviceRepository = new DeviceRepository(); + private DeviceService deviceService = new DeviceService(deviceRepository); + private final ExecutorService executor = Executors.newFixedThreadPool(10); + + private final HashMap pushers = new HashMap<>() {{ + put(TokenType.FCM, new FCM()); + put(TokenType.VoIPApns, new VoIPApns()); + }}; + + + private Pusher findPusher(TokenType tokenType){ + return this.pushers.get(tokenType); + } + + private List findPushTokens(String publicKey) { + List devices = this.deviceService.getDevicesByPK(publicKey); + List pushTokens = new java.util.ArrayList<>(); + for(Device device : devices){ + pushTokens.addAll(device.getTokens()); + } + return pushTokens; + } + + /** + * Отправить уведомление пользователю с publicKey, используя все его токены для отправки уведомления, если таковые имеются + * @param publicKey публичный ключ пользователя, которому нужно отправить уведомление + * @param data данные уведомления + */ + public void sendPush(String publicKey, HashMap data) { + executor.execute(() -> { + List pushTokens = this.findPushTokens(publicKey); + for(PushToken pushToken : pushTokens){ + Pusher pusher = this.findPusher(pushToken.getType()); + if(pusher != null){ + pusher.sendPush(pushToken.getToken(), data); + } + } + }); + } + + /** + * Отправить уведомление пользователям с publicKeys, используя все их токены для отправки уведомления, если таковые имеются + * @param publicKeys список публичных ключей пользователей, которым нужно отправить уведомление + * @param data данные уведомления + */ + public void sendPush(List publicKeys, HashMap data) { + executor.execute(() -> { + for(String publicKey : publicKeys){ + List pushTokens = this.findPushTokens(publicKey); + for(PushToken pushToken : pushTokens){ + Pusher pusher = this.findPusher(pushToken.getType()); + if(pusher != null){ + pusher.sendPush(pushToken.getToken(), data); + } + } + } + }); + } + + +} diff --git a/src/main/java/im/rosetta/service/dispatch/push/Pusher.java b/src/main/java/im/rosetta/service/dispatch/push/Pusher.java new file mode 100644 index 0000000..f5c9372 --- /dev/null +++ b/src/main/java/im/rosetta/service/dispatch/push/Pusher.java @@ -0,0 +1,14 @@ +package im.rosetta.service.dispatch.push; + +import java.util.HashMap; + +public abstract class Pusher { + + /** + * Вызывается при отправке PUSH уведомления, когда уже определен токен + * @param token токен для уведомления (FCM/VoIP/etc..) + * @param data данные уведомления + */ + public abstract void sendPush(String token, HashMap data); + +} diff --git a/src/main/java/im/rosetta/service/dispatch/FirebaseDispatcher.java b/src/main/java/im/rosetta/service/dispatch/push/dispatchers/FCM.java similarity index 61% rename from src/main/java/im/rosetta/service/dispatch/FirebaseDispatcher.java rename to src/main/java/im/rosetta/service/dispatch/push/dispatchers/FCM.java index 5367b0a..036e27a 100644 --- a/src/main/java/im/rosetta/service/dispatch/FirebaseDispatcher.java +++ b/src/main/java/im/rosetta/service/dispatch/push/dispatchers/FCM.java @@ -1,11 +1,8 @@ -package im.rosetta.service.dispatch; +package im.rosetta.service.dispatch.push.dispatchers; import java.io.FileInputStream; import java.io.IOException; import java.util.HashMap; -import java.util.List; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; import com.google.auth.oauth2.GoogleCredentials; import com.google.firebase.FirebaseApp; @@ -17,20 +14,12 @@ import com.google.firebase.messaging.FirebaseMessaging; import com.google.firebase.messaging.Message; import com.google.firebase.messaging.Notification; -import im.rosetta.database.repository.UserRepository; +import im.rosetta.service.dispatch.push.Pusher; import im.rosetta.service.dispatch.runtime.PushType; -import im.rosetta.service.services.UserService; -/** - * Класс для отправки push-уведомлений пользователям через Firebase Cloud Messaging (FCM). - */ -public class FirebaseDispatcher { +public class FCM extends Pusher { - private UserRepository userRepository = new UserRepository(); - private UserService userService = new UserService(userRepository); - private final ExecutorService executor = Executors.newFixedThreadPool(10); - - public FirebaseDispatcher() { + public FCM() { initializeFirebase(); } @@ -103,66 +92,14 @@ public class FirebaseDispatcher { return messageBuilder.build(); } - public void sendPushNotification(String publicKey, HashMap data) { - executor.submit(() -> { - try { - List tokens = userService.getNotificationsTokens(publicKey); - if (tokens == null || tokens.isEmpty()) { - return; - } - - for (String token : tokens) { - try { - Message message = this.buildMessage(token, data); - FirebaseMessaging.getInstance().send(message); - } catch (Exception e) { - e.printStackTrace(); - } - } - } catch (Exception e) { - e.printStackTrace(); - } - }); - } - - /** - * Отправляет push-уведомление нескольким пользователям (асинхронно) - * @param publicKeys список публичных ключей пользователей - * @param data данные уведомления - */ - public void sendPushNotification(List publicKeys, HashMap data) { - executor.submit(() -> { - for (String publicKey : publicKeys) { - sendPushNotificationSync(publicKey, data); - } - }); - } - - private void sendPushNotificationSync(String publicKey, HashMap data) { - try { - List tokens = userService.getNotificationsTokens(publicKey); - if (tokens == null || tokens.isEmpty()) { - return; - } - - for (String token : tokens) { - try { - Message message = this.buildMessage(token, data); - - FirebaseMessaging.getInstance().send(message); - } catch (Exception e) { - e.printStackTrace(); - } - } - } catch (Exception e) { - // Логирование ошибки + @Override + public void sendPush(String token, HashMap data) { + try{ + Message message = this.buildMessage(token, data); + FirebaseMessaging.getInstance().send(message); + }catch(Exception e){ + e.printStackTrace(); } } - /** - * Завершить работу executor при остановке приложения - */ - public void shutdown() { - executor.shutdown(); - } -} \ No newline at end of file +} diff --git a/src/main/java/im/rosetta/service/dispatch/push/dispatchers/VoIPApns.java b/src/main/java/im/rosetta/service/dispatch/push/dispatchers/VoIPApns.java new file mode 100644 index 0000000..2a37a94 --- /dev/null +++ b/src/main/java/im/rosetta/service/dispatch/push/dispatchers/VoIPApns.java @@ -0,0 +1,15 @@ +package im.rosetta.service.dispatch.push.dispatchers; + +import java.util.HashMap; + +import im.rosetta.service.dispatch.push.Pusher; + +public class VoIPApns extends Pusher { + + @Override + public void sendPush(String token, HashMap data) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'sendPush'"); + } + +} diff --git a/src/main/java/im/rosetta/service/services/UserService.java b/src/main/java/im/rosetta/service/services/UserService.java index 436bf1e..b087e7c 100644 --- a/src/main/java/im/rosetta/service/services/UserService.java +++ b/src/main/java/im/rosetta/service/services/UserService.java @@ -59,57 +59,4 @@ public class UserService extends Service { User user = this.getRepository().findByField("username", username); return user != null; } - - /** - * Подписывает пользователя на пуш уведомления, добавляя токен в его список токенов. Если токен уже был добавлен, то ничего не произойдет. - * @param user пользователь, которого нужно подписать на пуш уведомления - * @param notificationToken токен пуш уведомлений, который нужно добавить пользователю. Если токен уже был добавлен, то ничего не произойдет - */ - public void subscribeToPushNotifications(User user, String notificationToken) { - List tokens = user.getNotificationsTokens(); - if(tokens.contains(notificationToken)){ - return; - } - tokens.add(notificationToken); - user.setNotificationsTokens(tokens); - this.getRepository().update(user); - } - - /** - * Отписывает пользователя от пуш уведомлений, удаляя токен из его списка токенов. Если токена не было, то ничего не произойдет. - * @param user пользователь, которого нужно отписать от пуш уведомлений - * @param notificationToken токен пуш уведомлений, который нужно удалить у пользователя. Если токена не было, то ничего не произойдет - */ - public void unsubscribeFromPushNotifications(User user, String notificationToken) { - List tokens = user.getNotificationsTokens(); - if(!tokens.contains(notificationToken)){ - return; - } - tokens.remove(notificationToken); - user.setNotificationsTokens(tokens); - this.getRepository().update(user); - } - - /** - * Получает список токенов пуш уведомлений пользователя - * @param user пользователь, у которого нужно получить список токенов пуш уведомлений - * @return список токенов пуш уведомлений пользователя - */ - public List getNotificationsTokens(User user) { - return user.getNotificationsTokens(); - } - - /** - * Получает список токенов пуш уведомлений пользователя - * @param publicKey публичный ключ пользователя, у которого нужно получить список токенов пуш уведомлений - * @return список токенов пуш уведомлений пользователя - */ - public List getNotificationsTokens(String publicKey) { - User user = this.getRepository().findByField("publicKey", publicKey); - if(user == null){ - return null; - } - return user.getNotificationsTokens(); - } - } diff --git a/src/main/resources/hibernate.cfg.xml b/src/main/resources/hibernate.cfg.xml index 748caa2..b1dc3f9 100644 --- a/src/main/resources/hibernate.cfg.xml +++ b/src/main/resources/hibernate.cfg.xml @@ -9,6 +9,7 @@ +