summaryrefslogtreecommitdiff
path: root/pse-server/src/main/java/org/psesquared/server/model
diff options
context:
space:
mode:
Diffstat (limited to 'pse-server/src/main/java/org/psesquared/server/model')
-rw-r--r--pse-server/src/main/java/org/psesquared/server/model/Action.java45
-rw-r--r--pse-server/src/main/java/org/psesquared/server/model/Episode.java74
-rw-r--r--pse-server/src/main/java/org/psesquared/server/model/EpisodeAction.java101
-rw-r--r--pse-server/src/main/java/org/psesquared/server/model/Role.java28
-rw-r--r--pse-server/src/main/java/org/psesquared/server/model/Subscription.java87
-rw-r--r--pse-server/src/main/java/org/psesquared/server/model/SubscriptionAction.java62
-rw-r--r--pse-server/src/main/java/org/psesquared/server/model/User.java148
-rw-r--r--pse-server/src/main/java/org/psesquared/server/model/package-info.java8
8 files changed, 553 insertions, 0 deletions
diff --git a/pse-server/src/main/java/org/psesquared/server/model/Action.java b/pse-server/src/main/java/org/psesquared/server/model/Action.java
new file mode 100644
index 0000000..19b1c51
--- /dev/null
+++ b/pse-server/src/main/java/org/psesquared/server/model/Action.java
@@ -0,0 +1,45 @@
+package org.psesquared.server.model;
+
+import com.fasterxml.jackson.annotation.JsonValue;
+
+/**
+ * An enum with all different action types of an {@link EpisodeAction}.
+ */
+public enum Action {
+
+ /**
+ * The download action type.
+ */
+ DOWNLOAD,
+
+ /**
+ * The play action type.
+ */
+ PLAY,
+
+ /**
+ * The delete action type.
+ */
+ DELETE,
+
+ /**
+ * The new action type.
+ */
+ NEW,
+
+ /**
+ * The flattr action type.
+ */
+ FLATTR;
+
+ /**
+ * Getter for the value of the "action" JSON property.
+ *
+ * @return The JSON value
+ */
+ @JsonValue
+ public String getJsonProperty() {
+ return name().toLowerCase();
+ }
+
+}
diff --git a/pse-server/src/main/java/org/psesquared/server/model/Episode.java b/pse-server/src/main/java/org/psesquared/server/model/Episode.java
new file mode 100644
index 0000000..7a409fc
--- /dev/null
+++ b/pse-server/src/main/java/org/psesquared/server/model/Episode.java
@@ -0,0 +1,74 @@
+package org.psesquared.server.model;
+
+import jakarta.persistence.CascadeType;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.ManyToOne;
+import jakarta.persistence.OneToMany;
+import jakarta.persistence.Table;
+import java.io.Serializable;
+import java.util.List;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * An episode of a podcast.
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@Entity
+@Table(name = "episodes")
+public class Episode implements Serializable {
+
+ /**
+ * The primary key for the table.
+ */
+ @Id
+ @GeneratedValue(strategy=GenerationType.SEQUENCE)
+ @Column(name = "id", updatable = false)
+ private Long id;
+
+ /**
+ * The GUID of an episode.
+ */
+ @Column(name = "guid", unique = true)
+ private String guid;
+
+ /**
+ * The URL where the episode is located at.
+ */
+ @Column(name = "url", nullable = false)
+ private String url;
+
+ /**
+ * The title of the episode.
+ */
+ @Column(name = "title")
+ private String title;
+
+ /**
+ * The total length of an episode.
+ */
+ @Column(name = "total")
+ private int total;
+
+ /**
+ * The podcast the episode is a part of.
+ */
+ @ManyToOne(optional = false)
+ private Subscription subscription;
+
+ /**
+ * The actions of an episode.
+ */
+ @OneToMany(mappedBy = "episode", cascade = CascadeType.REMOVE)
+ private List<EpisodeAction> episodeActions;
+
+}
diff --git a/pse-server/src/main/java/org/psesquared/server/model/EpisodeAction.java b/pse-server/src/main/java/org/psesquared/server/model/EpisodeAction.java
new file mode 100644
index 0000000..a7e2375
--- /dev/null
+++ b/pse-server/src/main/java/org/psesquared/server/model/EpisodeAction.java
@@ -0,0 +1,101 @@
+package org.psesquared.server.model;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.ManyToOne;
+import jakarta.persistence.Table;
+import java.io.Serializable;
+import java.time.LocalDateTime;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.psesquared.server.episode.actions.api.controller.EpisodeActionPost;
+
+/**
+ * An action a user took regarding an episode of a podcast.
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@Entity
+@Table(name = "episode_actions")
+public class EpisodeAction implements Serializable {
+
+ /**
+ * The primary key for the table.
+ */
+ @JsonIgnore
+ @Id
+ @GeneratedValue(strategy=GenerationType.SEQUENCE)
+ @Column(name = "id", updatable = false)
+ private Long id;
+
+ /**
+ * The user who is responsible for the action.
+ */
+ @JsonIgnore
+ @ManyToOne(optional = false)
+ private User user;
+
+ /**
+ * The episode that is affected.
+ */
+ @JsonIgnore
+ @ManyToOne(optional = false)
+ private Episode episode;
+
+ /**
+ * The timestamp of when this action took place.
+ */
+ @Column(name = "timestamp",
+ nullable = false)
+ private LocalDateTime timestamp;
+
+ /**
+ * The type of action that happened.
+ */
+ @JsonProperty(required = true)
+ @Column(name = "action",
+ nullable = false,
+ updatable = false)
+ private Action action;
+
+ /**
+ * In case of play action: The starting time of the episode.
+ */
+ @Column(name = "started",
+ updatable = false)
+ private int started;
+
+ /**
+ * In case of play action: The time at which the episode was stopped.
+ */
+ @Column(name = "position",
+ nullable = false,
+ updatable = false)
+ private int position;
+
+ /**
+ * Generates a EpisodeActionPost from the given EpisodeAction for the
+ * EpisodeAction Controller.
+ *
+ * @return The generated EpisodeActionPost
+ */
+ public EpisodeActionPost toEpisodeActionPost() {
+ String podcastUrl = this.getEpisode().getSubscription().getUrl();
+ String episodeUrl = this.getEpisode().getUrl();
+ String title = this.getEpisode().getTitle();
+ String guid = this.getEpisode().getGuid();
+ int total = this.getEpisode().getTotal();
+ return
+ new EpisodeActionPost(podcastUrl, episodeUrl, title, guid, total, this);
+ }
+
+}
diff --git a/pse-server/src/main/java/org/psesquared/server/model/Role.java b/pse-server/src/main/java/org/psesquared/server/model/Role.java
new file mode 100644
index 0000000..37a316f
--- /dev/null
+++ b/pse-server/src/main/java/org/psesquared/server/model/Role.java
@@ -0,0 +1,28 @@
+package org.psesquared.server.model;
+
+/**
+ * Available user roles.
+ */
+public enum Role {
+
+ /**
+ * Standard role.
+ */
+ USER,
+
+ /**
+ * Privileged role.
+ */
+ ADMIN;
+
+ /**
+ * The starting index.
+ */
+ private static final int FIRST_INDEX = 0;
+
+ @Override
+ public String toString() {
+ return name().charAt(FIRST_INDEX) + name().substring(1).toLowerCase();
+ }
+
+}
diff --git a/pse-server/src/main/java/org/psesquared/server/model/Subscription.java b/pse-server/src/main/java/org/psesquared/server/model/Subscription.java
new file mode 100644
index 0000000..b130fca
--- /dev/null
+++ b/pse-server/src/main/java/org/psesquared/server/model/Subscription.java
@@ -0,0 +1,87 @@
+package org.psesquared.server.model;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import jakarta.persistence.CascadeType;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.NamedAttributeNode;
+import jakarta.persistence.NamedEntityGraph;
+import jakarta.persistence.OneToMany;
+import jakarta.persistence.Table;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.NonNull;
+
+/**
+ * A podcast that was subscribed.
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@Entity
+@Table(name = "subscriptions")
+@NamedEntityGraph(name = "graph.Subscription.episodes",
+ attributeNodes = @NamedAttributeNode("episodes"))
+public class Subscription implements Serializable {
+
+ /**
+ * A primary key for the table.
+ */
+ @JsonIgnore
+ @Id
+ @GeneratedValue(strategy=GenerationType.SEQUENCE)
+ @Column(name = "id", updatable = false)
+ private Long id;
+
+ /**
+ * The URL for the RSS-Feed of the Podcast.
+ */
+ @Column(name = "url", nullable = false)
+ private String url;
+
+ /**
+ * The title of the Podcast.
+ */
+ @Column(name = "title")
+ private String title;
+
+ /**
+ * Timestamp of the last time the RSS-Feed was fetched.
+ */
+ @Column(name = "timestamp")
+ private long timestamp;
+
+ /**
+ * The list of SubscriptionActions of this podcast.
+ */
+ @JsonIgnore
+ @OneToMany(mappedBy = "subscription",
+ cascade = CascadeType.REMOVE)
+ private List<SubscriptionAction> subscriptionActions;
+
+ /**
+ * The episodes of a subscription.
+ */
+ @JsonIgnore
+ @OneToMany(mappedBy = "subscription", cascade = CascadeType.REMOVE)
+ private final List<Episode> episodes = new ArrayList<>();
+
+ /**
+ * Adds an episode to the list of episodes.
+ *
+ * @param episode The to be added episode
+ */
+ public void addEpisode(@NonNull final Episode episode) {
+ this.episodes.add(episode);
+ }
+
+}
diff --git a/pse-server/src/main/java/org/psesquared/server/model/SubscriptionAction.java b/pse-server/src/main/java/org/psesquared/server/model/SubscriptionAction.java
new file mode 100644
index 0000000..3d850eb
--- /dev/null
+++ b/pse-server/src/main/java/org/psesquared/server/model/SubscriptionAction.java
@@ -0,0 +1,62 @@
+package org.psesquared.server.model;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.ManyToOne;
+import jakarta.persistence.Table;
+import java.io.Serializable;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * An action a user took regarding a podcast.
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@Entity
+@Table(name = "subscription_actions")
+public class SubscriptionAction implements Serializable {
+
+ /**
+ * The primary key for the table.
+ */
+ @Id
+ @GeneratedValue(strategy=GenerationType.SEQUENCE)
+ @Column(name = "id",
+ updatable = false)
+ private int id;
+
+ /**
+ * The user who took this action.
+ */
+ @ManyToOne(optional = false)
+ private User user;
+
+ /**
+ * The timestamp of when this action took place.
+ */
+ @Column(name = "timestamp",
+ nullable = false)
+ private long timestamp;
+
+ /**
+ * The podcast that was affected.
+ */
+ @ManyToOne(optional = false)
+ private Subscription subscription;
+
+ /**
+ * Whether the podcast was added or removed.
+ */
+ @Column(name = "added",
+ nullable = false)
+ private boolean added;
+
+}
diff --git a/pse-server/src/main/java/org/psesquared/server/model/User.java b/pse-server/src/main/java/org/psesquared/server/model/User.java
new file mode 100644
index 0000000..7279aae
--- /dev/null
+++ b/pse-server/src/main/java/org/psesquared/server/model/User.java
@@ -0,0 +1,148 @@
+package org.psesquared.server.model;
+
+import jakarta.persistence.CascadeType;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.OneToMany;
+import jakarta.persistence.Table;
+import java.util.Collection;
+import java.util.List;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.userdetails.UserDetails;
+
+/**
+ * A user that synchronizes their podcasts via this server.
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@Entity
+@Table(name = "users")
+public class User implements UserDetails {
+
+ /**
+ * The primary key for the table.
+ */
+ @Id
+ @GeneratedValue(strategy=GenerationType.SEQUENCE)
+ @Column(name = "id",
+ updatable = false)
+ private Long id;
+
+ /**
+ * The username of the user.
+ */
+ @Column(name = "username",
+ unique = true,
+ nullable = false,
+ updatable = false)
+ private String username;
+
+ /**
+ * The email address of the user.
+ */
+ @Column(name = "email",
+ unique = true,
+ nullable = false)
+ private String email;
+
+ /**
+ * The password of the user.
+ */
+ @Column(name = "password",
+ nullable = false)
+ private String password;
+
+ /**
+ * The verification status of the user.
+ */
+ @Column(name = "enabled",
+ nullable = false)
+ private boolean enabled;
+
+ /**
+ * Timestamp of when this user account was created.
+ */
+ @Column(name = "created_at",
+ nullable = false,
+ updatable = false)
+ private long createdAt;
+
+ /**
+ * The role of the user.
+ */
+ @Column(name = "role",
+ nullable = false)
+ private Role role;
+
+ /**
+ * The subscription actions the user made.
+ */
+ @OneToMany(mappedBy = "user",
+ cascade = CascadeType.REMOVE)
+ private List<SubscriptionAction> subscriptionActions;
+
+ /**
+ * The episode actions the user made.
+ */
+ @OneToMany(mappedBy = "user",
+ cascade = CascadeType.REMOVE)
+ private List<EpisodeAction> episodeActions;
+
+ /**
+ * Returns a collection with one {@link SimpleGrantedAuthority}
+ * with {@link #role}.
+ *
+ * @return The collection of granted authorities
+ */
+ @Override
+ public Collection<? extends GrantedAuthority> getAuthorities() {
+ return List.of(new SimpleGrantedAuthority(role.toString()));
+ }
+
+ /**
+ * Checks if this user account has not expired.
+ *
+ * @return {@code true} if the user account has not expired,
+ * <br>
+ * {@code false} otherwise
+ */
+ @Override
+ public boolean isAccountNonExpired() {
+ return enabled;
+ }
+
+ /**
+ * Checks if this user account is not locked.
+ *
+ * @return {@code true} if the user account is not locked,
+ * <br>
+ * {@code false} otherwise
+ */
+ @Override
+ public boolean isAccountNonLocked() {
+ return enabled;
+ }
+
+ /**
+ * Checks if this user account's credentials have not expired.
+ *
+ * @return {@code true} if the credentials have not expired,
+ * <br>
+ * {@code false} otherwise
+ */
+ @Override
+ public boolean isCredentialsNonExpired() {
+ return enabled;
+ }
+
+}
diff --git a/pse-server/src/main/java/org/psesquared/server/model/package-info.java b/pse-server/src/main/java/org/psesquared/server/model/package-info.java
new file mode 100644
index 0000000..2bb9c13
--- /dev/null
+++ b/pse-server/src/main/java/org/psesquared/server/model/package-info.java
@@ -0,0 +1,8 @@
+/**
+ * This package features all classes that map to database entities via ORM
+ * as well as some classes that the former rely on.
+ *
+ * @author PSE-Squared Team
+ * @version 1.0
+ */
+package org.psesquared.server.model;