migrate from swagger to openapi3

This commit is contained in:
Athou
2023-12-17 12:46:44 +01:00
parent 50fcdece86
commit b5d99b9661
36 changed files with 1299 additions and 1272 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -45,7 +45,7 @@
"react-redux": "^8.0.5",
"react-router-dom": "^6.11.2",
"react-swipeable": "^7.0.0",
"swagger-ui-react": "^4.18.3",
"swagger-ui-react": "^5.10.5",
"throttle-debounce": "^5.0.0",
"tinycon": "^0.6.8",
"use-local-storage": "^3.0.0",

View File

@@ -6,7 +6,7 @@ function ApiDocumentationPage() {
return (
// force white background because swagger is unreadable with dark theme
<Box style={{ backgroundColor: "#fff" }}>
<SwaggerUI url="swagger/swagger.json" />
<SwaggerUI url="openapi/openapi.json" />
</Box>
)
}

View File

@@ -54,7 +54,7 @@ export default defineConfig({
"/rest": "http://localhost:8083",
"/next": "http://localhost:8083",
"/ws": "ws://localhost:8083",
"/swagger": "http://localhost:8083",
"/openapi": "http://localhost:8083",
"/custom_css.css": "http://localhost:8083",
"/custom_js.js": "http://localhost:8083",
},

View File

@@ -124,41 +124,25 @@
</executions>
</plugin>
<plugin>
<groupId>com.github.kongchen</groupId>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-maven-plugin</artifactId>
<version>3.1.7</version>
<version>2.2.19</version>
<?m2e ignore?>
<configuration>
<apiSources>
<apiSource>
<locations>
<location>com.commafeed.frontend.resource</location>
<location>com.commafeed.frontend.model</location>
<location>com.commafeed.frontend.model.request</location>
</locations>
<swaggerDirectory>${project.build.directory}/classes/assets/swagger</swaggerDirectory>
<basePath>/rest</basePath>
<info>
<title>CommaFeed</title>
<version>${project.version}</version>
</info>
<securityDefinitions>
<securityDefinition>
<name>basicAuth</name>
<type>basic</type>
</securityDefinition>
</securityDefinitions>
<typesToSkip>
<typeToSkip>com.commafeed.backend.model.User</typeToSkip>
</typesToSkip>
</apiSource>
</apiSources>
<outputPath>${project.build.directory}/classes/assets/openapi</outputPath>
<outputFormat>JSONANDYAML</outputFormat>
<resourcePackages>
<package>com.commafeed.frontend.resource</package>
<package>com.commafeed.frontend.model</package>
<package>com.commafeed.frontend.model.request</package>
</resourcePackages>
<prettyPrint>true</prettyPrint>
</configuration>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>generate</goal>
<goal>resolve</goal>
</goals>
</execution>
</executions>
@@ -307,9 +291,9 @@
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-annotations</artifactId>
<version>1.5.22</version>
<version>2.2.19</version>
</dependency>
<dependency>

View File

@@ -4,36 +4,36 @@ import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.media.Schema.RequiredMode;
import lombok.Data;
@SuppressWarnings("serial")
@ApiModel(description = "Entry details")
@Schema(description = "Entry details")
@Data
public class Category implements Serializable {
@ApiModelProperty(value = "category id", required = true)
@Schema(description = "category id", requiredMode = RequiredMode.REQUIRED)
private String id;
@ApiModelProperty(value = "parent category id")
@Schema(description = "parent category id")
private String parentId;
@ApiModelProperty(value = "parent category name")
@Schema(description = "parent category name")
private String parentName;
@ApiModelProperty(value = "category id", required = true)
@Schema(description = "category id", requiredMode = RequiredMode.REQUIRED)
private String name;
@ApiModelProperty(value = "category children categories", required = true)
@Schema(description = "category children categories", requiredMode = RequiredMode.REQUIRED)
private List<Category> children = new ArrayList<>();
@ApiModelProperty(value = "category feeds", required = true)
@Schema(description = "category feeds", requiredMode = RequiredMode.REQUIRED)
private List<Subscription> feeds = new ArrayList<>();
@ApiModelProperty(value = "whether the category is expanded or collapsed", required = true)
@Schema(description = "whether the category is expanded or collapsed", requiredMode = RequiredMode.REQUIRED)
private boolean expanded;
@ApiModelProperty(value = "position of the category in the list", required = true)
@Schema(description = "position of the category in the list", requiredMode = RequiredMode.REQUIRED)
private int position;
}

View File

@@ -4,45 +4,45 @@ import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.media.Schema.RequiredMode;
import lombok.Data;
@SuppressWarnings("serial")
@ApiModel(description = "List of entries with some metadata")
@Schema(description = "List of entries with some metadata")
@Data
public class Entries implements Serializable {
@ApiModelProperty(value = "name of the feed or the category requested", required = true)
@Schema(description = "name of the feed or the category requested", requiredMode = RequiredMode.REQUIRED)
private String name;
@ApiModelProperty(value = "error or warning message")
@Schema(description = "error or warning message")
private String message;
@ApiModelProperty(value = "times the server tried to refresh the feed and failed", required = true)
@Schema(description = "times the server tried to refresh the feed and failed", requiredMode = RequiredMode.REQUIRED)
private int errorCount;
@ApiModelProperty(value = "URL of the website, extracted from the feed, only filled if querying for feed entries, not category entries")
@Schema(description = "URL of the website, extracted from the feed, only filled if querying for feed entries, not category entries")
private String feedLink;
@ApiModelProperty(value = "list generation timestamp", required = true)
@Schema(description = "list generation timestamp", requiredMode = RequiredMode.REQUIRED)
private long timestamp;
@ApiModelProperty(value = "if the query has more elements", required = true)
@Schema(description = "if the query has more elements", requiredMode = RequiredMode.REQUIRED)
private boolean hasMore;
@ApiModelProperty(value = "the requested offset")
@Schema(description = "the requested offset")
private int offset;
@ApiModelProperty(value = "the requested limit")
@Schema(description = "the requested limit")
private int limit;
@ApiModelProperty(value = "list of entries", required = true)
@Schema(description = "list of entries", requiredMode = RequiredMode.REQUIRED)
private List<Entry> entries = new ArrayList<>();
@ApiModelProperty(
value = "if true, the unread flag was ignored in the request, all entries are returned regardless of their read status",
required = true)
@Schema(
description = "if true, the unread flag was ignored in the request, all entries are returned regardless of their read status",
requiredMode = RequiredMode.REQUIRED)
private boolean ignoredReadStatus;
}

View File

@@ -21,88 +21,88 @@ import com.rometools.rome.feed.synd.SyndEnclosureImpl;
import com.rometools.rome.feed.synd.SyndEntry;
import com.rometools.rome.feed.synd.SyndEntryImpl;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.media.Schema.RequiredMode;
import lombok.Data;
@SuppressWarnings("serial")
@ApiModel(description = "Entry details")
@Schema(description = "Entry details")
@Data
public class Entry implements Serializable {
@ApiModelProperty(value = "entry id", required = true)
@Schema(description = "entry id", requiredMode = RequiredMode.REQUIRED)
private String id;
@ApiModelProperty(value = "entry guid", required = true)
@Schema(description = "entry guid", requiredMode = RequiredMode.REQUIRED)
private String guid;
@ApiModelProperty(value = "entry title", required = true)
@Schema(description = "entry title", requiredMode = RequiredMode.REQUIRED)
private String title;
@ApiModelProperty(value = "entry content", required = true)
@Schema(description = "entry content", requiredMode = RequiredMode.REQUIRED)
private String content;
@ApiModelProperty(value = "comma-separated list of categories")
@Schema(description = "comma-separated list of categories")
private String categories;
@ApiModelProperty(value = "whether entry content and title are rtl", required = true)
@Schema(description = "whether entry content and title are rtl", requiredMode = RequiredMode.REQUIRED)
private boolean rtl;
@ApiModelProperty(value = "entry author")
@Schema(description = "entry author")
private String author;
@ApiModelProperty(value = "entry enclosure url, if any")
@Schema(description = "entry enclosure url, if any")
private String enclosureUrl;
@ApiModelProperty(value = "entry enclosure mime type, if any")
@Schema(description = "entry enclosure mime type, if any")
private String enclosureType;
@ApiModelProperty(value = "entry media description, if any")
@Schema(description = "entry media description, if any")
private String mediaDescription;
@ApiModelProperty(value = "entry media thumbnail url, if any")
@Schema(description = "entry media thumbnail url, if any")
private String mediaThumbnailUrl;
@ApiModelProperty(value = "entry media thumbnail width, if any")
@Schema(description = "entry media thumbnail width, if any")
private Integer mediaThumbnailWidth;
@ApiModelProperty(value = "entry media thumbnail height, if any")
@Schema(description = "entry media thumbnail height, if any")
private Integer mediaThumbnailHeight;
@ApiModelProperty(value = "entry publication date", dataType = "number", required = true)
@Schema(description = "entry publication date", type = "number", requiredMode = RequiredMode.REQUIRED)
private Date date;
@ApiModelProperty(value = "entry insertion date in the database", dataType = "number", required = true)
@Schema(description = "entry insertion date in the database", type = "number", requiredMode = RequiredMode.REQUIRED)
private Date insertedDate;
@ApiModelProperty(value = "feed id", required = true)
@Schema(description = "feed id", requiredMode = RequiredMode.REQUIRED)
private String feedId;
@ApiModelProperty(value = "feed name", required = true)
@Schema(description = "feed name", requiredMode = RequiredMode.REQUIRED)
private String feedName;
@ApiModelProperty(value = "this entry's feed url", required = true)
@Schema(description = "this entry's feed url", requiredMode = RequiredMode.REQUIRED)
private String feedUrl;
@ApiModelProperty(value = "this entry's website url", required = true)
@Schema(description = "this entry's website url", requiredMode = RequiredMode.REQUIRED)
private String feedLink;
@ApiModelProperty(value = "The favicon url to use for this feed", required = true)
@Schema(description = "The favicon url to use for this feed", requiredMode = RequiredMode.REQUIRED)
private String iconUrl;
@ApiModelProperty(value = "entry url", required = true)
@Schema(description = "entry url", requiredMode = RequiredMode.REQUIRED)
private String url;
@ApiModelProperty(value = "read status", required = true)
@Schema(description = "read status", requiredMode = RequiredMode.REQUIRED)
private boolean read;
@ApiModelProperty(value = "starred status", required = true)
@Schema(description = "starred status", requiredMode = RequiredMode.REQUIRED)
private boolean starred;
@ApiModelProperty(value = "whether the entry is still markable (old entry statuses are discarded)", required = true)
@Schema(description = "whether the entry is still markable (old entry statuses are discarded)", requiredMode = RequiredMode.REQUIRED)
private boolean markable;
@ApiModelProperty(value = "tags", required = true)
@Schema(description = "tags", requiredMode = RequiredMode.REQUIRED)
private List<String> tags;
public static Entry build(FeedEntryStatus status, boolean proxyImages) {

View File

@@ -2,19 +2,19 @@ package com.commafeed.frontend.model;
import java.io.Serializable;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.media.Schema.RequiredMode;
import lombok.Data;
@SuppressWarnings("serial")
@ApiModel(description = "Feed details")
@Schema(description = "Feed details")
@Data
public class FeedInfo implements Serializable {
@ApiModelProperty(value = "url", required = true)
@Schema(description = "url", requiredMode = RequiredMode.REQUIRED)
private String url;
@ApiModelProperty(value = "title", required = true)
@Schema(description = "title", requiredMode = RequiredMode.REQUIRED)
private String title;
}

View File

@@ -2,34 +2,34 @@ package com.commafeed.frontend.model;
import java.io.Serializable;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.media.Schema.RequiredMode;
import lombok.Data;
@SuppressWarnings("serial")
@ApiModel(description = "Server infos")
@Schema(description = "Server infos")
@Data
public class ServerInfo implements Serializable {
@ApiModelProperty
@Schema
private String announcement;
@ApiModelProperty(required = true)
@Schema(requiredMode = RequiredMode.REQUIRED)
private String version;
@ApiModelProperty(required = true)
@Schema(requiredMode = RequiredMode.REQUIRED)
private String gitCommit;
@ApiModelProperty(required = true)
@Schema(requiredMode = RequiredMode.REQUIRED)
private boolean allowRegistrations;
@ApiModelProperty
@Schema
private String googleAnalyticsCode;
@ApiModelProperty(required = true)
@Schema(requiredMode = RequiredMode.REQUIRED)
private boolean smtpEnabled;
@ApiModelProperty(required = true)
@Schema(requiredMode = RequiredMode.REQUIRED)
private boolean demoAccountEnabled;
}

View File

@@ -2,76 +2,84 @@ package com.commafeed.frontend.model;
import java.io.Serializable;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.media.Schema.RequiredMode;
import lombok.Data;
@SuppressWarnings("serial")
@ApiModel(description = "User settings")
@Schema(description = "User settings")
@Data
public class Settings implements Serializable {
@ApiModelProperty(value = "user's preferred language, english if none", required = true)
@Schema(description = "user's preferred language, english if none", requiredMode = RequiredMode.REQUIRED)
private String language;
@ApiModelProperty(value = "user reads all entries or unread entries only", allowableValues = "all,unread", required = true)
@Schema(
description = "user reads all entries or unread entries only",
allowableValues = "all,unread",
requiredMode = RequiredMode.REQUIRED)
private String readingMode;
@ApiModelProperty(value = "user reads entries in ascending or descending order", allowableValues = "asc,desc", required = true)
@Schema(
description = "user reads entries in ascending or descending order",
allowableValues = "asc,desc",
requiredMode = RequiredMode.REQUIRED)
private String readingOrder;
@ApiModelProperty(value = "user wants category and feeds with no unread entries shown", required = true)
@Schema(description = "user wants category and feeds with no unread entries shown", requiredMode = RequiredMode.REQUIRED)
private boolean showRead;
@ApiModelProperty(value = "In expanded view, scroll through entries mark them as read", required = true)
@Schema(description = "In expanded view, scroll through entries mark them as read", requiredMode = RequiredMode.REQUIRED)
private boolean scrollMarks;
@ApiModelProperty(value = "user's custom css for the website")
@Schema(description = "user's custom css for the website")
private String customCss;
@ApiModelProperty(value = "user's custom js for the website")
@Schema(description = "user's custom js for the website")
private String customJs;
@ApiModelProperty(value = "user's preferred scroll speed when navigating between entries", required = true)
@Schema(description = "user's preferred scroll speed when navigating between entries", requiredMode = RequiredMode.REQUIRED)
private int scrollSpeed;
@ApiModelProperty(value = "always scroll selected entry to the top of the page, even if it fits entirely on screen", required = true)
@Schema(
description = "always scroll selected entry to the top of the page, even if it fits entirely on screen",
requiredMode = RequiredMode.REQUIRED)
private boolean alwaysScrollToEntry;
@ApiModelProperty(value = "ask for confirmation when marking all entries as read", required = true)
@Schema(description = "ask for confirmation when marking all entries as read", requiredMode = RequiredMode.REQUIRED)
private boolean markAllAsReadConfirmation;
@ApiModelProperty(value = "show commafeed's own context menu on right click", required = true)
@Schema(description = "show commafeed's own context menu on right click", requiredMode = RequiredMode.REQUIRED)
private boolean customContextMenu;
@ApiModelProperty(value = "sharing settings", required = true)
@Schema(description = "sharing settings", requiredMode = RequiredMode.REQUIRED)
private SharingSettings sharingSettings = new SharingSettings();
@ApiModel(description = "User sharing settings")
@Schema(description = "User sharing settings")
@Data
public static class SharingSettings implements Serializable {
@ApiModelProperty(required = true)
@Schema(requiredMode = RequiredMode.REQUIRED)
private boolean email;
@ApiModelProperty(required = true)
@Schema(requiredMode = RequiredMode.REQUIRED)
private boolean gmail;
@ApiModelProperty(required = true)
@Schema(requiredMode = RequiredMode.REQUIRED)
private boolean facebook;
@ApiModelProperty(required = true)
@Schema(requiredMode = RequiredMode.REQUIRED)
private boolean twitter;
@ApiModelProperty(required = true)
@Schema(requiredMode = RequiredMode.REQUIRED)
private boolean tumblr;
@ApiModelProperty(required = true)
@Schema(requiredMode = RequiredMode.REQUIRED)
private boolean pocket;
@ApiModelProperty(required = true)
@Schema(requiredMode = RequiredMode.REQUIRED)
private boolean instapaper;
@ApiModelProperty(required = true)
@Schema(requiredMode = RequiredMode.REQUIRED)
private boolean buffer;
}
}

View File

@@ -8,55 +8,55 @@ import com.commafeed.backend.model.Feed;
import com.commafeed.backend.model.FeedCategory;
import com.commafeed.backend.model.FeedSubscription;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.media.Schema.RequiredMode;
import lombok.Data;
@SuppressWarnings("serial")
@ApiModel(description = "User information")
@Schema(description = "User information")
@Data
public class Subscription implements Serializable {
@ApiModelProperty(value = "subscription id", required = true)
@Schema(description = "subscription id", requiredMode = RequiredMode.REQUIRED)
private Long id;
@ApiModelProperty(value = "subscription name", required = true)
@Schema(description = "subscription name", requiredMode = RequiredMode.REQUIRED)
private String name;
@ApiModelProperty(value = "error message while fetching the feed")
@Schema(description = "error message while fetching the feed")
private String message;
@ApiModelProperty(value = "error count", required = true)
@Schema(description = "error count", requiredMode = RequiredMode.REQUIRED)
private int errorCount;
@ApiModelProperty(value = "last time the feed was refreshed", dataType = "number")
@Schema(description = "last time the feed was refreshed", type = "number")
private Date lastRefresh;
@ApiModelProperty(value = "next time the feed refresh is planned, null if refresh is already queued", dataType = "number")
@Schema(description = "next time the feed refresh is planned, null if refresh is already queued", type = "number")
private Date nextRefresh;
@ApiModelProperty(value = "this subscription's feed url", required = true)
@Schema(description = "this subscription's feed url", requiredMode = RequiredMode.REQUIRED)
private String feedUrl;
@ApiModelProperty(value = "this subscription's website url", required = true)
@Schema(description = "this subscription's website url", requiredMode = RequiredMode.REQUIRED)
private String feedLink;
@ApiModelProperty(value = "The favicon url to use for this feed", required = true)
@Schema(description = "The favicon url to use for this feed", requiredMode = RequiredMode.REQUIRED)
private String iconUrl;
@ApiModelProperty(value = "unread count", required = true)
@Schema(description = "unread count", requiredMode = RequiredMode.REQUIRED)
private long unread;
@ApiModelProperty(value = "category id")
@Schema(description = "category id")
private String categoryId;
@ApiModelProperty("position of the subscription's in the list")
@Schema(description = "position of the subscription's in the list")
private int position;
@ApiModelProperty(value = "date of the newest item", dataType = "number")
@Schema(description = "date of the newest item", type = "number")
private Date newestItemTime;
@ApiModelProperty(value = "JEXL string evaluated on new entries to mark them as read if they do not match")
@Schema(description = "JEXL string evaluated on new entries to mark them as read if they do not match")
private String filter;
public static Subscription build(FeedSubscription subscription, UnreadCount unreadCount) {

View File

@@ -3,22 +3,21 @@ package com.commafeed.frontend.model;
import java.io.Serializable;
import java.util.Date;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@SuppressWarnings("serial")
@ApiModel(description = "Unread count")
@Schema(description = "Unread count")
@Data
public class UnreadCount implements Serializable {
@ApiModelProperty
@Schema
private long feedId;
@ApiModelProperty
@Schema
private long unreadCount;
@ApiModelProperty(dataType = "number")
@Schema(type = "number")
private Date newestItemTime;
public UnreadCount() {

View File

@@ -3,40 +3,40 @@ package com.commafeed.frontend.model;
import java.io.Serializable;
import java.util.Date;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.media.Schema.RequiredMode;
import lombok.Data;
@SuppressWarnings("serial")
@ApiModel(description = "User information")
@Schema(description = "User information")
@Data
public class UserModel implements Serializable {
@ApiModelProperty(value = "user id", required = true)
@Schema(description = "user id", requiredMode = RequiredMode.REQUIRED)
private Long id;
@ApiModelProperty(value = "user name", required = true)
@Schema(description = "user name", requiredMode = RequiredMode.REQUIRED)
private String name;
@ApiModelProperty("user email, if any")
@Schema(description = "user email, if any")
private String email;
@ApiModelProperty("api key")
@Schema(description = "api key")
private String apiKey;
@ApiModelProperty(value = "user password, never returned by the api")
@Schema(description = "user password, never returned by the api")
private String password;
@ApiModelProperty(value = "account status", required = true)
@Schema(description = "account status", requiredMode = RequiredMode.REQUIRED)
private boolean enabled;
@ApiModelProperty(value = "account creation date", dataType = "number")
@Schema(description = "account creation date", type = "number")
private Date created;
@ApiModelProperty(value = "last login date", dataType = "number")
@Schema(description = "last login date", type = "number")
private Date lastLogin;
@ApiModelProperty(value = "user is admin", required = true)
@Schema(description = "user is admin", requiredMode = RequiredMode.REQUIRED)
private boolean admin;
}

View File

@@ -5,21 +5,21 @@ import java.io.Serializable;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Size;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.media.Schema.RequiredMode;
import lombok.Data;
@SuppressWarnings("serial")
@ApiModel(description = "Add Category Request")
@Schema(description = "Add Category Request")
@Data
public class AddCategoryRequest implements Serializable {
@ApiModelProperty(value = "name", required = true)
@Schema(description = "name", requiredMode = RequiredMode.REQUIRED)
@NotEmpty
@Size(max = 128)
private String name;
@ApiModelProperty(value = "parent category id, if any")
@Schema(description = "parent category id, if any")
@Size(max = 128)
private String parentId;

View File

@@ -4,27 +4,27 @@ import java.io.Serializable;
import javax.validation.constraints.Size;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.media.Schema.RequiredMode;
import lombok.Data;
@SuppressWarnings("serial")
@ApiModel(description = "Category modification request")
@Schema(description = "Category modification request")
@Data
public class CategoryModificationRequest implements Serializable {
@ApiModelProperty(value = "id", required = true)
@Schema(description = "id", requiredMode = RequiredMode.REQUIRED)
private Long id;
@ApiModelProperty(value = "new name, null if not changed")
@Schema(description = "new name, null if not changed")
@Size(max = 128)
private String name;
@ApiModelProperty(value = "new parent category id")
@Schema(description = "new parent category id")
@Size(max = 128)
private String parentId;
@ApiModelProperty(value = "new display position, null if not changed")
@Schema(description = "new display position, null if not changed")
private Integer position;
}

View File

@@ -2,19 +2,19 @@ package com.commafeed.frontend.model.request;
import java.io.Serializable;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.media.Schema.RequiredMode;
import lombok.Data;
@SuppressWarnings("serial")
@ApiModel(description = "Mark Request")
@Schema(description = "Mark Request")
@Data
public class CollapseRequest implements Serializable {
@ApiModelProperty(value = "category id", required = true)
@Schema(description = "category id", requiredMode = RequiredMode.REQUIRED)
private Long id;
@ApiModelProperty(value = "collapse", required = true)
@Schema(description = "collapse", requiredMode = RequiredMode.REQUIRED)
private boolean collapse;
}

View File

@@ -5,16 +5,16 @@ import java.io.Serializable;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Size;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.media.Schema.RequiredMode;
import lombok.Data;
@SuppressWarnings("serial")
@ApiModel(description = "Feed information request")
@Schema(description = "Feed information request")
@Data
public class FeedInfoRequest implements Serializable {
@ApiModelProperty(value = "feed url", required = true)
@Schema(description = "feed url", requiredMode = RequiredMode.REQUIRED)
@NotEmpty
@Size(max = 4096)
private String url;

View File

@@ -4,30 +4,30 @@ import java.io.Serializable;
import javax.validation.constraints.Size;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.media.Schema.RequiredMode;
import lombok.Data;
@SuppressWarnings("serial")
@ApiModel(description = "Feed modification request")
@Schema(description = "Feed modification request")
@Data
public class FeedModificationRequest implements Serializable {
@ApiModelProperty(value = "id", required = true)
@Schema(description = "id", requiredMode = RequiredMode.REQUIRED)
private Long id;
@ApiModelProperty(value = "new name, null if not changed")
@Schema(description = "new name, null if not changed")
@Size(max = 128)
private String name;
@ApiModelProperty(value = "new parent category id")
@Schema(description = "new parent category id")
@Size(max = 128)
private String categoryId;
@ApiModelProperty(value = "new display position, null if not changed")
@Schema(description = "new display position, null if not changed")
private Integer position;
@ApiModelProperty(value = "JEXL string evaluated on new entries to mark them as read if they do not match")
@Schema(description = "JEXL string evaluated on new entries to mark them as read if they do not match")
@Size(max = 4096)
private String filter;

View File

@@ -2,16 +2,16 @@ package com.commafeed.frontend.model.request;
import java.io.Serializable;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.media.Schema.RequiredMode;
import lombok.Data;
@SuppressWarnings("serial")
@ApiModel
@Schema
@Data
public class IDRequest implements Serializable {
@ApiModelProperty(required = true)
@Schema(requiredMode = RequiredMode.REQUIRED)
private Long id;
}

View File

@@ -5,20 +5,20 @@ import java.io.Serializable;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Size;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.media.Schema.RequiredMode;
import lombok.Data;
@SuppressWarnings("serial")
@Data
@ApiModel
@Schema
public class LoginRequest implements Serializable {
@ApiModelProperty(value = "username", required = true)
@Schema(description = "username", requiredMode = RequiredMode.REQUIRED)
@Size(min = 3, max = 32)
private String name;
@ApiModelProperty(value = "password", required = true)
@Schema(description = "password", requiredMode = RequiredMode.REQUIRED)
@NotEmpty
@Size(max = 128)
private String password;

View File

@@ -6,33 +6,37 @@ import java.util.List;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Size;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.media.Schema.RequiredMode;
import lombok.Data;
@SuppressWarnings("serial")
@ApiModel(description = "Mark Request")
@Schema(description = "Mark Request")
@Data
public class MarkRequest implements Serializable {
@ApiModelProperty(value = "entry id, category id, 'all' or 'starred'", required = true)
@Schema(description = "entry id, category id, 'all' or 'starred'", requiredMode = RequiredMode.REQUIRED)
@NotEmpty
@Size(max = 128)
private String id;
@ApiModelProperty(value = "mark as read or unread", required = true)
@Schema(description = "mark as read or unread", requiredMode = RequiredMode.REQUIRED)
private boolean read;
@ApiModelProperty(
value = "only entries older than this, pass the timestamp you got from the entry list to prevent marking an entry that was not retrieved",
required = false)
@Schema(
description = "only entries older than this, pass the timestamp you got from the entry list to prevent marking an entry that was not retrieved",
requiredMode = RequiredMode.NOT_REQUIRED)
private Long olderThan;
@ApiModelProperty(value = "only mark read if a feed has these keywords in the title or rss content", required = false)
@Schema(
description = "only mark read if a feed has these keywords in the title or rss content",
requiredMode = RequiredMode.NOT_REQUIRED)
@Size(max = 128)
private String keywords;
@ApiModelProperty(value = "if marking a category or 'all', exclude those subscriptions from the marking", required = false)
@Schema(
description = "if marking a category or 'all', exclude those subscriptions from the marking",
requiredMode = RequiredMode.NOT_REQUIRED)
private List<Long> excludedSubscriptions;
}

View File

@@ -5,16 +5,16 @@ import java.util.List;
import javax.validation.Valid;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.media.Schema.RequiredMode;
import lombok.Data;
@SuppressWarnings("serial")
@ApiModel(description = "Multiple Mark Request")
@Schema(description = "Multiple Mark Request")
@Data
public class MultipleMarkRequest implements Serializable {
@ApiModelProperty(value = "list of mark requests", required = true)
@Schema(description = "list of mark requests", requiredMode = RequiredMode.REQUIRED)
private List<@Valid MarkRequest> requests;
}

View File

@@ -6,16 +6,16 @@ import javax.validation.constraints.Email;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Size;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.media.Schema.RequiredMode;
import lombok.Data;
@SuppressWarnings("serial")
@Data
@ApiModel
@Schema
public class PasswordResetRequest implements Serializable {
@ApiModelProperty(value = "email address for password recovery", required = true)
@Schema(description = "email address for password recovery", requiredMode = RequiredMode.REQUIRED)
@Email
@NotEmpty
@Size(max = 255)

View File

@@ -7,28 +7,28 @@ import javax.validation.constraints.Size;
import com.commafeed.frontend.auth.ValidPassword;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.media.Schema.RequiredMode;
import lombok.Data;
@SuppressWarnings("serial")
@ApiModel(description = "Profile modification request")
@Schema(description = "Profile modification request")
@Data
public class ProfileModificationRequest implements Serializable {
@ApiModelProperty(value = "current user password, required to change profile data", required = true)
@Schema(description = "current user password, required to change profile data", requiredMode = RequiredMode.REQUIRED)
@NotEmpty
@Size(max = 128)
private String currentPassword;
@ApiModelProperty(value = "changes email of the user, if specified")
@Schema(description = "changes email of the user, if specified")
@Size(max = 255)
private String email;
@ApiModelProperty(value = "changes password of the user, if specified")
@Schema(description = "changes password of the user, if specified")
@ValidPassword
private String newPassword;
@ApiModelProperty(value = "generate a new api key")
@Schema(description = "generate a new api key")
private boolean newApiKey;
}

View File

@@ -8,26 +8,26 @@ import javax.validation.constraints.Size;
import com.commafeed.frontend.auth.ValidPassword;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.media.Schema.RequiredMode;
import lombok.Data;
@SuppressWarnings("serial")
@Data
@ApiModel
@Schema
public class RegistrationRequest implements Serializable {
@ApiModelProperty(value = "username, between 3 and 32 characters", required = true)
@Schema(description = "username, between 3 and 32 characters", requiredMode = RequiredMode.REQUIRED)
@NotEmpty
@Size(min = 3, max = 32)
private String name;
@ApiModelProperty(value = "password, minimum 6 characters", required = true)
@Schema(description = "password, minimum 6 characters", requiredMode = RequiredMode.REQUIRED)
@NotEmpty
@ValidPassword
private String password;
@ApiModelProperty(value = "email address for password recovery", required = true)
@Schema(description = "email address for password recovery", requiredMode = RequiredMode.REQUIRED)
@Email
@NotEmpty
@Size(max = 255)

View File

@@ -5,24 +5,24 @@ import java.io.Serializable;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Size;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.media.Schema.RequiredMode;
import lombok.Data;
@SuppressWarnings("serial")
@ApiModel(description = "Star Request")
@Schema(description = "Star Request")
@Data
public class StarRequest implements Serializable {
@ApiModelProperty(value = "id", required = true)
@Schema(description = "id", requiredMode = RequiredMode.REQUIRED)
@NotEmpty
@Size(max = 128)
private String id;
@ApiModelProperty(value = "feed id", required = true)
@Schema(description = "feed id", requiredMode = RequiredMode.REQUIRED)
private Long feedId;
@ApiModelProperty(value = "starred or not", required = true)
@Schema(description = "starred or not", requiredMode = RequiredMode.REQUIRED)
private boolean starred;
}

View File

@@ -5,26 +5,26 @@ import java.io.Serializable;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Size;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.media.Schema.RequiredMode;
import lombok.Data;
@SuppressWarnings("serial")
@ApiModel(description = "Subscription request")
@Schema(description = "Subscription request")
@Data
public class SubscribeRequest implements Serializable {
@ApiModelProperty(value = "url of the feed", required = true)
@Schema(description = "url of the feed", requiredMode = RequiredMode.REQUIRED)
@NotEmpty
@Size(max = 4096)
private String url;
@ApiModelProperty(value = "name of the feed for the user", required = true)
@Schema(description = "name of the feed for the user", requiredMode = RequiredMode.REQUIRED)
@NotEmpty
@Size(max = 128)
private String title;
@ApiModelProperty(value = "id of the user category to place the feed in")
@Schema(description = "id of the user category to place the feed in")
@Size(max = 128)
private String categoryId;

View File

@@ -3,19 +3,19 @@ package com.commafeed.frontend.model.request;
import java.io.Serializable;
import java.util.List;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.media.Schema.RequiredMode;
import lombok.Data;
@SuppressWarnings("serial")
@ApiModel(description = "Tag Request")
@Schema(description = "Tag Request")
@Data
public class TagRequest implements Serializable {
@ApiModelProperty(value = "entry id", required = true)
@Schema(description = "entry id", requiredMode = RequiredMode.REQUIRED)
private Long entryId;
@ApiModelProperty(value = "tags", required = true)
@Schema(description = "tags", requiredMode = RequiredMode.REQUIRED)
private List<String> tags;
}

View File

@@ -37,13 +37,15 @@ import com.google.common.base.Preconditions;
import com.google.common.collect.Sets;
import io.dropwizard.hibernate.UnitOfWork;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import lombok.RequiredArgsConstructor;
@Path("/admin")
@Api(value = "/admin")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@RequiredArgsConstructor(onConstructor = @__({ @Inject }))
@@ -60,10 +62,12 @@ public class AdminREST {
@Path("/user/save")
@POST
@UnitOfWork
@ApiOperation(value = "Save or update a user", notes = "Save or update a user. If the id is not specified, a new user will be created")
@Operation(
summary = "Save or update a user",
description = "Save or update a user. If the id is not specified, a new user will be created")
@Timed
public Response adminSaveUser(@ApiParam(hidden = true) @SecurityCheck(Role.ADMIN) User user,
@ApiParam(required = true) UserModel userModel) {
public Response adminSaveUser(@Parameter(hidden = true) @SecurityCheck(Role.ADMIN) User user,
@Parameter(required = true) UserModel userModel) {
Preconditions.checkNotNull(userModel);
Preconditions.checkNotNull(userModel.getName());
@@ -116,10 +120,13 @@ public class AdminREST {
@Path("/user/get/{id}")
@GET
@UnitOfWork
@ApiOperation(value = "Get user information", notes = "Get user information", response = UserModel.class)
@Operation(
summary = "Get user information",
description = "Get user information",
responses = { @ApiResponse(content = @Content(schema = @Schema(implementation = UserModel.class))) })
@Timed
public Response adminGetUser(@ApiParam(hidden = true) @SecurityCheck(Role.ADMIN) User user,
@ApiParam(value = "user id", required = true) @PathParam("id") Long id) {
public Response adminGetUser(@Parameter(hidden = true) @SecurityCheck(Role.ADMIN) User user,
@Parameter(description = "user id", required = true) @PathParam("id") Long id) {
Preconditions.checkNotNull(id);
User u = userDAO.findById(id);
UserModel userModel = new UserModel();
@@ -134,9 +141,12 @@ public class AdminREST {
@Path("/user/getAll")
@GET
@UnitOfWork
@ApiOperation(value = "Get all users", notes = "Get all users", response = UserModel.class, responseContainer = "List")
@Operation(
summary = "Get all users",
description = "Get all users",
responses = { @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = UserModel.class)))) })
@Timed
public Response adminGetUsers(@ApiParam(hidden = true) @SecurityCheck(Role.ADMIN) User user) {
public Response adminGetUsers(@Parameter(hidden = true) @SecurityCheck(Role.ADMIN) User user) {
Map<Long, UserModel> users = new HashMap<>();
for (UserRole role : userRoleDAO.findAll()) {
User u = role.getUser();
@@ -162,10 +172,10 @@ public class AdminREST {
@Path("/user/delete")
@POST
@UnitOfWork
@ApiOperation(value = "Delete a user", notes = "Delete a user, and all his subscriptions")
@Operation(summary = "Delete a user", description = "Delete a user, and all his subscriptions")
@Timed
public Response adminDeleteUser(@ApiParam(hidden = true) @SecurityCheck(Role.ADMIN) User user,
@ApiParam(required = true) IDRequest req) {
public Response adminDeleteUser(@Parameter(hidden = true) @SecurityCheck(Role.ADMIN) User user,
@Parameter(required = true) IDRequest req) {
Preconditions.checkNotNull(req);
Preconditions.checkNotNull(req.getId());
@@ -183,18 +193,21 @@ public class AdminREST {
@Path("/settings")
@GET
@UnitOfWork
@ApiOperation(value = "Retrieve application settings", notes = "Retrieve application settings", response = ApplicationSettings.class)
@Operation(
summary = "Retrieve application settings",
description = "Retrieve application settings",
responses = { @ApiResponse(content = @Content(schema = @Schema(implementation = ApplicationSettings.class))) })
@Timed
public Response getApplicationSettings(@ApiParam(hidden = true) @SecurityCheck(Role.ADMIN) User user) {
public Response getApplicationSettings(@Parameter(hidden = true) @SecurityCheck(Role.ADMIN) User user) {
return Response.ok(config.getApplicationSettings()).build();
}
@Path("/metrics")
@GET
@UnitOfWork
@ApiOperation(value = "Retrieve server metrics")
@Operation(summary = "Retrieve server metrics")
@Timed
public Response getMetrics(@ApiParam(hidden = true) @SecurityCheck(Role.ADMIN) User user) {
public Response getMetrics(@Parameter(hidden = true) @SecurityCheck(Role.ADMIN) User user) {
return Response.ok(metrics).build();
}

View File

@@ -64,14 +64,16 @@ import com.rometools.rome.feed.synd.SyndFeedImpl;
import com.rometools.rome.io.SyndFeedOutput;
import io.dropwizard.hibernate.UnitOfWork;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@Path("/category")
@Api(value = "/category")
@Slf4j
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@@ -93,24 +95,26 @@ public class CategoryREST {
@Path("/entries")
@GET
@UnitOfWork
@ApiOperation(value = "Get category entries", notes = "Get a list of category entries", response = Entries.class)
@Operation(
summary = "Get category entries",
description = "Get a list of category entries",
responses = { @ApiResponse(content = @Content(schema = @Schema(implementation = Entries.class))) })
@Timed
public Response getCategoryEntries(@ApiParam(hidden = true) @SecurityCheck(apiKeyAllowed = true) User user,
@ApiParam(value = "id of the category, 'all' or 'starred'", required = true) @QueryParam("id") String id,
@ApiParam(
value = "all entries or only unread ones",
allowableValues = "all,unread",
public Response getCategoryEntries(@Parameter(hidden = true) @SecurityCheck(apiKeyAllowed = true) User user,
@Parameter(description = "id of the category, 'all' or 'starred'", required = true) @QueryParam("id") String id,
@Parameter(
description = "all entries or only unread ones",
required = true) @DefaultValue("unread") @QueryParam("readType") ReadingMode readType,
@ApiParam(value = "only entries newer than this") @QueryParam("newerThan") Long newerThan,
@ApiParam(value = "offset for paging") @DefaultValue("0") @QueryParam("offset") int offset,
@ApiParam(value = "limit for paging, default 20, maximum 1000") @DefaultValue("20") @QueryParam("limit") int limit,
@ApiParam(value = "ordering", allowableValues = "asc,desc") @QueryParam("order") @DefaultValue("desc") ReadingOrder order,
@ApiParam(
value = "search for keywords in either the title or the content of the entries, separated by spaces, 3 characters minimum") @QueryParam("keywords") String keywords,
@ApiParam(value = "return only entry ids") @DefaultValue("false") @QueryParam("onlyIds") boolean onlyIds,
@ApiParam(
value = "comma-separated list of excluded subscription ids") @QueryParam("excludedSubscriptionIds") String excludedSubscriptionIds,
@ApiParam(value = "keep only entries tagged with this tag") @QueryParam("tag") String tag) {
@Parameter(description = "only entries newer than this") @QueryParam("newerThan") Long newerThan,
@Parameter(description = "offset for paging") @DefaultValue("0") @QueryParam("offset") int offset,
@Parameter(description = "limit for paging, default 20, maximum 1000") @DefaultValue("20") @QueryParam("limit") int limit,
@Parameter(description = "ordering") @QueryParam("order") @DefaultValue("desc") ReadingOrder order,
@Parameter(
description = "search for keywords in either the title or the content of the entries, separated by spaces, 3 characters minimum") @QueryParam("keywords") String keywords,
@Parameter(description = "return only entry ids") @DefaultValue("false") @QueryParam("onlyIds") boolean onlyIds,
@Parameter(
description = "comma-separated list of excluded subscription ids") @QueryParam("excludedSubscriptionIds") String excludedSubscriptionIds,
@Parameter(description = "keep only entries tagged with this tag") @QueryParam("tag") String tag) {
Preconditions.checkNotNull(readType);
@@ -186,25 +190,24 @@ public class CategoryREST {
@Path("/entriesAsFeed")
@GET
@UnitOfWork
@ApiOperation(value = "Get category entries as feed", notes = "Get a feed of category entries")
@Operation(summary = "Get category entries as feed", description = "Get a feed of category entries")
@Produces(MediaType.APPLICATION_XML)
@Timed
public Response getCategoryEntriesAsFeed(@ApiParam(hidden = true) @SecurityCheck(apiKeyAllowed = true) User user,
@ApiParam(value = "id of the category, 'all' or 'starred'", required = true) @QueryParam("id") String id,
@ApiParam(
value = "all entries or only unread ones",
allowableValues = "all,unread",
public Response getCategoryEntriesAsFeed(@Parameter(hidden = true) @SecurityCheck(apiKeyAllowed = true) User user,
@Parameter(description = "id of the category, 'all' or 'starred'", required = true) @QueryParam("id") String id,
@Parameter(
description = "all entries or only unread ones",
required = true) @DefaultValue("all") @QueryParam("readType") ReadingMode readType,
@ApiParam(value = "only entries newer than this") @QueryParam("newerThan") Long newerThan,
@ApiParam(value = "offset for paging") @DefaultValue("0") @QueryParam("offset") int offset,
@ApiParam(value = "limit for paging, default 20, maximum 1000") @DefaultValue("20") @QueryParam("limit") int limit,
@ApiParam(value = "date ordering", allowableValues = "asc,desc") @QueryParam("order") @DefaultValue("desc") ReadingOrder order,
@ApiParam(
value = "search for keywords in either the title or the content of the entries, separated by spaces, 3 characters minimum") @QueryParam("keywords") String keywords,
@ApiParam(value = "return only entry ids") @DefaultValue("false") @QueryParam("onlyIds") boolean onlyIds,
@ApiParam(
value = "comma-separated list of excluded subscription ids") @QueryParam("excludedSubscriptionIds") String excludedSubscriptionIds,
@ApiParam(value = "keep only entries tagged with this tag") @QueryParam("tag") String tag) {
@Parameter(description = "only entries newer than this") @QueryParam("newerThan") Long newerThan,
@Parameter(description = "offset for paging") @DefaultValue("0") @QueryParam("offset") int offset,
@Parameter(description = "limit for paging, default 20, maximum 1000") @DefaultValue("20") @QueryParam("limit") int limit,
@Parameter(description = "date ordering") @QueryParam("order") @DefaultValue("desc") ReadingOrder order,
@Parameter(
description = "search for keywords in either the title or the content of the entries, separated by spaces, 3 characters minimum") @QueryParam("keywords") String keywords,
@Parameter(description = "return only entry ids") @DefaultValue("false") @QueryParam("onlyIds") boolean onlyIds,
@Parameter(
description = "comma-separated list of excluded subscription ids") @QueryParam("excludedSubscriptionIds") String excludedSubscriptionIds,
@Parameter(description = "keep only entries tagged with this tag") @QueryParam("tag") String tag) {
Response response = getCategoryEntries(user, id, readType, newerThan, offset, limit, order, keywords, onlyIds,
excludedSubscriptionIds, tag);
@@ -234,10 +237,10 @@ public class CategoryREST {
@Path("/mark")
@POST
@UnitOfWork
@ApiOperation(value = "Mark category entries", notes = "Mark feed entries of this category as read")
@Operation(summary = "Mark category entries", description = "Mark feed entries of this category as read")
@Timed
public Response markCategoryEntries(@ApiParam(hidden = true) @SecurityCheck User user,
@Valid @ApiParam(value = "category id, or 'all'", required = true) MarkRequest req) {
public Response markCategoryEntries(@Parameter(hidden = true) @SecurityCheck User user,
@Valid @Parameter(description = "category id, or 'all'", required = true) MarkRequest req) {
Preconditions.checkNotNull(req);
Preconditions.checkNotNull(req.getId());
@@ -276,10 +279,13 @@ public class CategoryREST {
@Path("/add")
@POST
@UnitOfWork
@ApiOperation(value = "Add a category", notes = "Add a new feed category", response = Long.class)
@Operation(
summary = "Add a category",
description = "Add a new feed category",
responses = { @ApiResponse(content = @Content(schema = @Schema(implementation = Long.class))) })
@Timed
public Response addCategory(@ApiParam(hidden = true) @SecurityCheck User user,
@Valid @ApiParam(required = true) AddCategoryRequest req) {
public Response addCategory(@Parameter(hidden = true) @SecurityCheck User user,
@Valid @Parameter(required = true) AddCategoryRequest req) {
Preconditions.checkNotNull(req);
Preconditions.checkNotNull(req.getName());
@@ -301,9 +307,9 @@ public class CategoryREST {
@POST
@Path("/delete")
@UnitOfWork
@ApiOperation(value = "Delete a category", notes = "Delete an existing feed category")
@Operation(summary = "Delete a category", description = "Delete an existing feed category")
@Timed
public Response deleteCategory(@ApiParam(hidden = true) @SecurityCheck User user, @ApiParam(required = true) IDRequest req) {
public Response deleteCategory(@Parameter(hidden = true) @SecurityCheck User user, @Parameter(required = true) IDRequest req) {
Preconditions.checkNotNull(req);
Preconditions.checkNotNull(req.getId());
@@ -334,10 +340,10 @@ public class CategoryREST {
@POST
@Path("/modify")
@UnitOfWork
@ApiOperation(value = "Rename a category", notes = "Rename an existing feed category")
@Operation(summary = "Rename a category", description = "Rename an existing feed category")
@Timed
public Response modifyCategory(@ApiParam(hidden = true) @SecurityCheck User user,
@Valid @ApiParam(required = true) CategoryModificationRequest req) {
public Response modifyCategory(@Parameter(hidden = true) @SecurityCheck User user,
@Valid @Parameter(required = true) CategoryModificationRequest req) {
Preconditions.checkNotNull(req);
Preconditions.checkNotNull(req.getId());
@@ -390,9 +396,9 @@ public class CategoryREST {
@POST
@Path("/collapse")
@UnitOfWork
@ApiOperation(value = "Collapse a category", notes = "Save collapsed or expanded status for a category")
@Operation(summary = "Collapse a category", description = "Save collapsed or expanded status for a category")
@Timed
public Response collapseCategory(@ApiParam(hidden = true) @SecurityCheck User user, @ApiParam(required = true) CollapseRequest req) {
public Response collapseCategory(@Parameter(hidden = true) @SecurityCheck User user, @Parameter(required = true) CollapseRequest req) {
Preconditions.checkNotNull(req);
Preconditions.checkNotNull(req.getId());
@@ -409,9 +415,11 @@ public class CategoryREST {
@GET
@Path("/unreadCount")
@UnitOfWork
@ApiOperation(value = "Get unread count for feed subscriptions", response = UnreadCount.class, responseContainer = "List")
@Operation(
summary = "Get unread count for feed subscriptions",
responses = { @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = UnreadCount.class)))) })
@Timed
public Response getUnreadCount(@ApiParam(hidden = true) @SecurityCheck(apiKeyAllowed = true) User user) {
public Response getUnreadCount(@Parameter(hidden = true) @SecurityCheck(apiKeyAllowed = true) User user) {
Map<Long, UnreadCount> unreadCount = feedSubscriptionService.getUnreadCount(user);
return Response.ok(Lists.newArrayList(unreadCount.values())).build();
}
@@ -419,9 +427,12 @@ public class CategoryREST {
@GET
@Path("/get")
@UnitOfWork
@ApiOperation(value = "Get root category", notes = "Get all categories and subscriptions of the user", response = Category.class)
@Operation(
summary = "Get root category",
description = "Get all categories and subscriptions of the user",
responses = { @ApiResponse(content = @Content(schema = @Schema(implementation = Category.class))) })
@Timed
public Response getRootCategory(@ApiParam(hidden = true) @SecurityCheck User user) {
public Response getRootCategory(@Parameter(hidden = true) @SecurityCheck User user) {
Category root = cache.getUserRootCategory(user);
if (root == null) {
log.debug("tree cache miss for {}", user.getId());

View File

@@ -26,13 +26,11 @@ import com.commafeed.frontend.model.request.TagRequest;
import com.google.common.base.Preconditions;
import io.dropwizard.hibernate.UnitOfWork;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import lombok.RequiredArgsConstructor;
@Path("/entry")
@Api(value = "/entry")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@RequiredArgsConstructor(onConstructor = @__({ @Inject }))
@@ -46,10 +44,10 @@ public class EntryREST {
@Path("/mark")
@POST
@UnitOfWork
@ApiOperation(value = "Mark a feed entry", notes = "Mark a feed entry as read/unread")
@Operation(summary = "Mark a feed entry", description = "Mark a feed entry as read/unread")
@Timed
public Response markEntry(@ApiParam(hidden = true) @SecurityCheck User user,
@Valid @ApiParam(value = "Mark Request", required = true) MarkRequest req) {
public Response markEntry(@Parameter(hidden = true) @SecurityCheck User user,
@Valid @Parameter(description = "Mark Request", required = true) MarkRequest req) {
Preconditions.checkNotNull(req);
Preconditions.checkNotNull(req.getId());
@@ -60,10 +58,10 @@ public class EntryREST {
@Path("/markMultiple")
@POST
@UnitOfWork
@ApiOperation(value = "Mark multiple feed entries", notes = "Mark feed entries as read/unread")
@Operation(summary = "Mark multiple feed entries", description = "Mark feed entries as read/unread")
@Timed
public Response markEntries(@ApiParam(hidden = true) @SecurityCheck User user,
@Valid @ApiParam(value = "Multiple Mark Request", required = true) MultipleMarkRequest req) {
public Response markEntries(@Parameter(hidden = true) @SecurityCheck User user,
@Valid @Parameter(description = "Multiple Mark Request", required = true) MultipleMarkRequest req) {
Preconditions.checkNotNull(req);
Preconditions.checkNotNull(req.getRequests());
@@ -77,10 +75,10 @@ public class EntryREST {
@Path("/star")
@POST
@UnitOfWork
@ApiOperation(value = "Mark a feed entry", notes = "Mark a feed entry as read/unread")
@Operation(summary = "Mark a feed entry", description = "Mark a feed entry as read/unread")
@Timed
public Response starEntry(@ApiParam(hidden = true) @SecurityCheck User user,
@Valid @ApiParam(value = "Star Request", required = true) StarRequest req) {
public Response starEntry(@Parameter(hidden = true) @SecurityCheck User user,
@Valid @Parameter(description = "Star Request", required = true) StarRequest req) {
Preconditions.checkNotNull(req);
Preconditions.checkNotNull(req.getId());
Preconditions.checkNotNull(req.getFeedId());
@@ -93,9 +91,9 @@ public class EntryREST {
@Path("/tags")
@GET
@UnitOfWork
@ApiOperation(value = "Get list of tags for the user", notes = "Get list of tags for the user")
@Operation(summary = "Get list of tags for the user", description = "Get list of tags for the user")
@Timed
public Response getTags(@ApiParam(hidden = true) @SecurityCheck User user) {
public Response getTags(@Parameter(hidden = true) @SecurityCheck User user) {
List<String> tags = feedEntryTagDAO.findByUser(user);
return Response.ok(tags).build();
}
@@ -103,10 +101,10 @@ public class EntryREST {
@Path("/tag")
@POST
@UnitOfWork
@ApiOperation(value = "Set feed entry tags")
@Operation(summary = "Set feed entry tags")
@Timed
public Response tagEntry(@ApiParam(hidden = true) @SecurityCheck User user,
@Valid @ApiParam(value = "Tag Request", required = true) TagRequest req) {
public Response tagEntry(@Parameter(hidden = true) @SecurityCheck User user,
@Valid @Parameter(description = "Tag Request", required = true) TagRequest req) {
Preconditions.checkNotNull(req);
Preconditions.checkNotNull(req.getEntryId());

View File

@@ -84,14 +84,15 @@ import com.rometools.rome.io.SyndFeedOutput;
import com.rometools.rome.io.WireFeedOutput;
import io.dropwizard.hibernate.UnitOfWork;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@Path("/feed")
@Api(value = "/feed")
@Slf4j
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@@ -130,21 +131,23 @@ public class FeedREST {
@Path("/entries")
@GET
@UnitOfWork
@ApiOperation(value = "Get feed entries", notes = "Get a list of feed entries", response = Entries.class)
@Operation(
summary = "Get feed entries",
description = "Get a list of feed entries",
responses = { @ApiResponse(content = @Content(schema = @Schema(implementation = Entries.class))) })
@Timed
public Response getFeedEntries(@ApiParam(hidden = true) @SecurityCheck(apiKeyAllowed = true) User user,
@ApiParam(value = "id of the feed", required = true) @QueryParam("id") String id,
@ApiParam(
value = "all entries or only unread ones",
allowableValues = "all,unread",
public Response getFeedEntries(@Parameter(hidden = true) @SecurityCheck(apiKeyAllowed = true) User user,
@Parameter(description = "id of the feed", required = true) @QueryParam("id") String id,
@Parameter(
description = "all entries or only unread ones",
required = true) @DefaultValue("unread") @QueryParam("readType") ReadingMode readType,
@ApiParam(value = "only entries newer than this") @QueryParam("newerThan") Long newerThan,
@ApiParam(value = "offset for paging") @DefaultValue("0") @QueryParam("offset") int offset,
@ApiParam(value = "limit for paging, default 20, maximum 1000") @DefaultValue("20") @QueryParam("limit") int limit,
@ApiParam(value = "ordering", allowableValues = "asc,desc") @QueryParam("order") @DefaultValue("desc") ReadingOrder order,
@ApiParam(
value = "search for keywords in either the title or the content of the entries, separated by spaces, 3 characters minimum") @QueryParam("keywords") String keywords,
@ApiParam(value = "return only entry ids") @DefaultValue("false") @QueryParam("onlyIds") boolean onlyIds) {
@Parameter(description = "only entries newer than this") @QueryParam("newerThan") Long newerThan,
@Parameter(description = "offset for paging") @DefaultValue("0") @QueryParam("offset") int offset,
@Parameter(description = "limit for paging, default 20, maximum 1000") @DefaultValue("20") @QueryParam("limit") int limit,
@Parameter(description = "ordering") @QueryParam("order") @DefaultValue("desc") ReadingOrder order,
@Parameter(
description = "search for keywords in either the title or the content of the entries, separated by spaces, 3 characters minimum") @QueryParam("keywords") String keywords,
@Parameter(description = "return only entry ids") @DefaultValue("false") @QueryParam("onlyIds") boolean onlyIds) {
Preconditions.checkNotNull(id);
Preconditions.checkNotNull(readType);
@@ -196,22 +199,21 @@ public class FeedREST {
@Path("/entriesAsFeed")
@GET
@UnitOfWork
@ApiOperation(value = "Get feed entries as a feed", notes = "Get a feed of feed entries")
@Operation(summary = "Get feed entries as a feed", description = "Get a feed of feed entries")
@Produces(MediaType.APPLICATION_XML)
@Timed
public Response getFeedEntriesAsFeed(@ApiParam(hidden = true) @SecurityCheck(apiKeyAllowed = true) User user,
@ApiParam(value = "id of the feed", required = true) @QueryParam("id") String id,
@ApiParam(
value = "all entries or only unread ones",
allowableValues = "all,unread",
public Response getFeedEntriesAsFeed(@Parameter(hidden = true) @SecurityCheck(apiKeyAllowed = true) User user,
@Parameter(description = "id of the feed", required = true) @QueryParam("id") String id,
@Parameter(
description = "all entries or only unread ones",
required = true) @DefaultValue("all") @QueryParam("readType") ReadingMode readType,
@ApiParam(value = "only entries newer than this") @QueryParam("newerThan") Long newerThan,
@ApiParam(value = "offset for paging") @DefaultValue("0") @QueryParam("offset") int offset,
@ApiParam(value = "limit for paging, default 20, maximum 1000") @DefaultValue("20") @QueryParam("limit") int limit,
@ApiParam(value = "date ordering", allowableValues = "asc,desc") @QueryParam("order") @DefaultValue("desc") ReadingOrder order,
@ApiParam(
value = "search for keywords in either the title or the content of the entries, separated by spaces, 3 characters minimum") @QueryParam("keywords") String keywords,
@ApiParam(value = "return only entry ids") @DefaultValue("false") @QueryParam("onlyIds") boolean onlyIds) {
@Parameter(description = "only entries newer than this") @QueryParam("newerThan") Long newerThan,
@Parameter(description = "offset for paging") @DefaultValue("0") @QueryParam("offset") int offset,
@Parameter(description = "limit for paging, default 20, maximum 1000") @DefaultValue("20") @QueryParam("limit") int limit,
@Parameter(description = "date ordering") @QueryParam("order") @DefaultValue("desc") ReadingOrder order,
@Parameter(
description = "search for keywords in either the title or the content of the entries, separated by spaces, 3 characters minimum") @QueryParam("keywords") String keywords,
@Parameter(description = "return only entry ids") @DefaultValue("false") @QueryParam("onlyIds") boolean onlyIds) {
Response response = getFeedEntries(user, id, readType, newerThan, offset, limit, order, keywords, onlyIds);
if (response.getStatus() != Status.OK.getStatusCode()) {
@@ -257,10 +259,13 @@ public class FeedREST {
@POST
@Path("/fetch")
@UnitOfWork
@ApiOperation(value = "Fetch a feed", notes = "Fetch a feed by its url", response = FeedInfo.class)
@Operation(
summary = "Fetch a feed",
description = "Fetch a feed by its url",
responses = { @ApiResponse(content = @Content(schema = @Schema(implementation = FeedInfo.class))) })
@Timed
public Response fetchFeed(@ApiParam(hidden = true) @SecurityCheck User user,
@Valid @ApiParam(value = "feed url", required = true) FeedInfoRequest req) {
public Response fetchFeed(@Parameter(hidden = true) @SecurityCheck User user,
@Valid @Parameter(description = "feed url", required = true) FeedInfoRequest req) {
Preconditions.checkNotNull(req);
Preconditions.checkNotNull(req.getUrl());
@@ -280,9 +285,9 @@ public class FeedREST {
@Path("/refreshAll")
@GET
@UnitOfWork
@ApiOperation(value = "Queue all feeds of the user for refresh", notes = "Manually add all feeds of the user to the refresh queue")
@Operation(summary = "Queue all feeds of the user for refresh", description = "Manually add all feeds of the user to the refresh queue")
@Timed
public Response queueAllForRefresh(@ApiParam(hidden = true) @SecurityCheck User user) {
public Response queueAllForRefresh(@Parameter(hidden = true) @SecurityCheck User user) {
feedSubscriptionService.refreshAll(user);
return Response.ok().build();
}
@@ -290,10 +295,10 @@ public class FeedREST {
@Path("/refresh")
@POST
@UnitOfWork
@ApiOperation(value = "Queue a feed for refresh", notes = "Manually add a feed to the refresh queue")
@Operation(summary = "Queue a feed for refresh", description = "Manually add a feed to the refresh queue")
@Timed
public Response queueForRefresh(@ApiParam(hidden = true) @SecurityCheck User user,
@ApiParam(value = "Feed id", required = true) IDRequest req) {
public Response queueForRefresh(@Parameter(hidden = true) @SecurityCheck User user,
@Parameter(description = "Feed id", required = true) IDRequest req) {
Preconditions.checkNotNull(req);
Preconditions.checkNotNull(req.getId());
@@ -310,10 +315,10 @@ public class FeedREST {
@Path("/mark")
@POST
@UnitOfWork
@ApiOperation(value = "Mark feed entries", notes = "Mark feed entries as read (unread is not supported)")
@Operation(summary = "Mark feed entries", description = "Mark feed entries as read (unread is not supported)")
@Timed
public Response markFeedEntries(@ApiParam(hidden = true) @SecurityCheck User user,
@Valid @ApiParam(value = "Mark request", required = true) MarkRequest req) {
public Response markFeedEntries(@Parameter(hidden = true) @SecurityCheck User user,
@Valid @Parameter(description = "Mark request", required = true) MarkRequest req) {
Preconditions.checkNotNull(req);
Preconditions.checkNotNull(req.getId());
@@ -331,10 +336,12 @@ public class FeedREST {
@GET
@Path("/get/{id}")
@UnitOfWork
@ApiOperation(value = "get feed", response = Subscription.class)
@Operation(
summary = "get feed",
responses = { @ApiResponse(content = @Content(schema = @Schema(implementation = Subscription.class))) })
@Timed
public Response getFeed(@ApiParam(hidden = true) @SecurityCheck User user,
@ApiParam(value = "user id", required = true) @PathParam("id") Long id) {
public Response getFeed(@Parameter(hidden = true) @SecurityCheck User user,
@Parameter(description = "user id", required = true) @PathParam("id") Long id) {
Preconditions.checkNotNull(id);
FeedSubscription sub = feedSubscriptionDAO.findById(user, id);
@@ -348,10 +355,10 @@ public class FeedREST {
@GET
@Path("/favicon/{id}")
@UnitOfWork
@ApiOperation(value = "Fetch a feed's icon", notes = "Fetch a feed's icon")
@Operation(summary = "Fetch a feed's icon", description = "Fetch a feed's icon")
@Timed
public Response getFeedFavicon(@ApiParam(hidden = true) @SecurityCheck User user,
@ApiParam(value = "subscription id", required = true) @PathParam("id") Long id) {
public Response getFeedFavicon(@Parameter(hidden = true) @SecurityCheck User user,
@Parameter(description = "subscription id", required = true) @PathParam("id") Long id) {
Preconditions.checkNotNull(id);
FeedSubscription subscription = feedSubscriptionDAO.findById(user, id);
@@ -379,10 +386,13 @@ public class FeedREST {
@POST
@Path("/subscribe")
@UnitOfWork
@ApiOperation(value = "Subscribe to a feed", notes = "Subscribe to a feed", response = Long.class)
@Operation(
summary = "Subscribe to a feed",
description = "Subscribe to a feed",
responses = { @ApiResponse(content = @Content(schema = @Schema(implementation = Long.class))) })
@Timed
public Response subscribe(@ApiParam(hidden = true) @SecurityCheck User user,
@Valid @ApiParam(value = "subscription request", required = true) SubscribeRequest req) {
public Response subscribe(@Parameter(hidden = true) @SecurityCheck User user,
@Valid @Parameter(description = "subscription request", required = true) SubscribeRequest req) {
Preconditions.checkNotNull(req);
Preconditions.checkNotNull(req.getTitle());
Preconditions.checkNotNull(req.getUrl());
@@ -407,10 +417,10 @@ public class FeedREST {
@GET
@Path("/subscribe")
@UnitOfWork
@ApiOperation(value = "Subscribe to a feed", notes = "Subscribe to a feed")
@Operation(summary = "Subscribe to a feed", description = "Subscribe to a feed")
@Timed
public Response subscribeFromUrl(@ApiParam(hidden = true) @SecurityCheck User user,
@ApiParam(value = "feed url", required = true) @QueryParam("url") String url) {
public Response subscribeFromUrl(@Parameter(hidden = true) @SecurityCheck User user,
@Parameter(description = "feed url", required = true) @QueryParam("url") String url) {
try {
Preconditions.checkNotNull(url);
@@ -436,9 +446,9 @@ public class FeedREST {
@POST
@Path("/unsubscribe")
@UnitOfWork
@ApiOperation(value = "Unsubscribe from a feed", notes = "Unsubscribe from a feed")
@Operation(summary = "Unsubscribe from a feed", description = "Unsubscribe from a feed")
@Timed
public Response unsubscribe(@ApiParam(hidden = true) @SecurityCheck User user, @ApiParam(required = true) IDRequest req) {
public Response unsubscribe(@Parameter(hidden = true) @SecurityCheck User user, @Parameter(required = true) IDRequest req) {
Preconditions.checkNotNull(req);
Preconditions.checkNotNull(req.getId());
@@ -453,10 +463,10 @@ public class FeedREST {
@POST
@Path("/modify")
@UnitOfWork
@ApiOperation(value = "Modify a subscription", notes = "Modify a feed subscription")
@Operation(summary = "Modify a subscription", description = "Modify a feed subscription")
@Timed
public Response modifyFeed(@ApiParam(hidden = true) @SecurityCheck User user,
@Valid @ApiParam(value = "subscription id", required = true) FeedModificationRequest req) {
public Response modifyFeed(@Parameter(hidden = true) @SecurityCheck User user,
@Valid @Parameter(description = "subscription id", required = true) FeedModificationRequest req) {
Preconditions.checkNotNull(req);
Preconditions.checkNotNull(req.getId());
@@ -514,10 +524,10 @@ public class FeedREST {
@Path("/import")
@UnitOfWork
@Consumes(MediaType.MULTIPART_FORM_DATA)
@ApiOperation(value = "OPML import", notes = "Import an OPML file, posted as a FORM with the 'file' name")
@Operation(summary = "OPML import", description = "Import an OPML file, posted as a FORM with the 'file' name")
@Timed
public Response importOpml(@ApiParam(hidden = true) @SecurityCheck User user,
@ApiParam(value = "ompl file", required = true) @FormDataParam("file") InputStream input) {
public Response importOpml(@Parameter(hidden = true) @SecurityCheck User user,
@Parameter(description = "ompl file", required = true) @FormDataParam("file") InputStream input) {
if (CommaFeedApplication.USERNAME_DEMO.equals(user.getName())) {
return Response.status(Status.FORBIDDEN).entity("Import is disabled for the demo account").build();
}
@@ -535,9 +545,9 @@ public class FeedREST {
@Path("/export")
@UnitOfWork
@Produces(MediaType.APPLICATION_XML)
@ApiOperation(value = "OPML export", notes = "Export an OPML file of the user's subscriptions")
@Operation(summary = "OPML export", description = "Export an OPML file of the user's subscriptions")
@Timed
public Response exportOpml(@ApiParam(hidden = true) @SecurityCheck User user) {
public Response exportOpml(@Parameter(hidden = true) @SecurityCheck User user) {
Opml opml = opmlExporter.export(user);
WireFeedOutput output = new WireFeedOutput();
String opmlString = null;

View File

@@ -0,0 +1,16 @@
package com.commafeed.frontend.resource;
import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import io.swagger.v3.oas.annotations.enums.SecuritySchemeType;
import io.swagger.v3.oas.annotations.info.Info;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.security.SecurityScheme;
import io.swagger.v3.oas.annotations.servers.Server;
@OpenAPIDefinition(
info = @Info(title = "CommaFeed API"),
servers = { @Server(description = "CommaFeed API", url = "../rest") },
security = { @SecurityRequirement(name = "basicAuth") })
@SecurityScheme(name = "basicAuth", type = SecuritySchemeType.HTTP, scheme = "basic")
public class OpenAPI {
}

View File

@@ -23,13 +23,14 @@ import com.commafeed.frontend.auth.SecurityCheck;
import com.commafeed.frontend.model.ServerInfo;
import io.dropwizard.hibernate.UnitOfWork;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import lombok.RequiredArgsConstructor;
@Path("/server")
@Api(value = "/server")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@RequiredArgsConstructor(onConstructor = @__({ @Inject }))
@@ -42,7 +43,10 @@ public class ServerREST {
@Path("/get")
@GET
@UnitOfWork
@ApiOperation(value = "Get server infos", notes = "Get server infos", response = ServerInfo.class)
@Operation(
summary = "Get server infos",
description = "Get server infos",
responses = { @ApiResponse(content = @Content(schema = @Schema(implementation = ServerInfo.class))) })
@Timed
public Response getServerInfos() {
ServerInfo infos = new ServerInfo();
@@ -59,11 +63,11 @@ public class ServerREST {
@Path("/proxy")
@GET
@UnitOfWork
@ApiOperation(value = "proxy image")
@Operation(summary = "proxy image")
@Produces("image/png")
@Timed
public Response getProxiedImage(@ApiParam(hidden = true) @SecurityCheck User user,
@ApiParam(value = "image url", required = true) @QueryParam("u") String url) {
public Response getProxiedImage(@Parameter(hidden = true) @SecurityCheck User user,
@Parameter(description = "image url", required = true) @QueryParam("u") String url) {
if (!config.getApplicationSettings().getImageProxyEnabled()) {
return Response.status(Status.FORBIDDEN).build();
}

View File

@@ -53,14 +53,15 @@ import com.commafeed.frontend.session.SessionHelper;
import com.google.common.base.Preconditions;
import io.dropwizard.hibernate.UnitOfWork;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@Path("/user")
@Api(value = "/user")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@Slf4j
@@ -79,9 +80,12 @@ public class UserREST {
@Path("/settings")
@GET
@UnitOfWork
@ApiOperation(value = "Retrieve user settings", notes = "Retrieve user settings", response = Settings.class)
@Operation(
summary = "Retrieve user settings",
description = "Retrieve user settings",
responses = { @ApiResponse(content = @Content(schema = @Schema(implementation = Settings.class))) })
@Timed
public Response getUserSettings(@ApiParam(hidden = true) @SecurityCheck User user) {
public Response getUserSettings(@Parameter(hidden = true) @SecurityCheck User user) {
Settings s = new Settings();
UserSettings settings = userSettingsDAO.findByUser(user);
if (settings != null) {
@@ -133,9 +137,9 @@ public class UserREST {
@Path("/settings")
@POST
@UnitOfWork
@ApiOperation(value = "Save user settings", notes = "Save user settings")
@Operation(summary = "Save user settings", description = "Save user settings")
@Timed
public Response saveUserSettings(@ApiParam(hidden = true) @SecurityCheck User user, @ApiParam(required = true) Settings settings) {
public Response saveUserSettings(@Parameter(hidden = true) @SecurityCheck User user, @Parameter(required = true) Settings settings) {
Preconditions.checkNotNull(settings);
UserSettings s = userSettingsDAO.findByUser(user);
@@ -172,9 +176,11 @@ public class UserREST {
@Path("/profile")
@GET
@UnitOfWork
@ApiOperation(value = "Retrieve user's profile", response = UserModel.class)
@Operation(
summary = "Retrieve user's profile",
responses = { @ApiResponse(content = @Content(schema = @Schema(implementation = UserModel.class))) })
@Timed
public Response getUserProfile(@ApiParam(hidden = true) @SecurityCheck User user) {
public Response getUserProfile(@Parameter(hidden = true) @SecurityCheck User user) {
UserModel userModel = new UserModel();
userModel.setId(user.getId());
userModel.setName(user.getName());
@@ -192,10 +198,10 @@ public class UserREST {
@Path("/profile")
@POST
@UnitOfWork
@ApiOperation(value = "Save user's profile")
@Operation(summary = "Save user's profile")
@Timed
public Response saveUserProfile(@ApiParam(hidden = true) @SecurityCheck User user,
@Valid @ApiParam(required = true) ProfileModificationRequest request) {
public Response saveUserProfile(@Parameter(hidden = true) @SecurityCheck User user,
@Valid @Parameter(required = true) ProfileModificationRequest request) {
if (CommaFeedApplication.USERNAME_DEMO.equals(user.getName())) {
return Response.status(Status.FORBIDDEN).build();
}
@@ -231,10 +237,10 @@ public class UserREST {
@Path("/register")
@POST
@UnitOfWork
@ApiOperation(value = "Register a new account")
@Operation(summary = "Register a new account")
@Timed
public Response registerUser(@Valid @ApiParam(required = true) RegistrationRequest req,
@Context @ApiParam(hidden = true) SessionHelper sessionHelper) {
public Response registerUser(@Valid @Parameter(required = true) RegistrationRequest req,
@Context @Parameter(hidden = true) SessionHelper sessionHelper) {
try {
User registeredUser = userService.register(req.getName(), req.getPassword(), req.getEmail(),
Collections.singletonList(Role.USER));
@@ -249,10 +255,10 @@ public class UserREST {
@Path("/login")
@POST
@UnitOfWork
@ApiOperation(value = "Login and create a session")
@Operation(summary = "Login and create a session")
@Timed
public Response login(@Valid @ApiParam(required = true) LoginRequest req,
@ApiParam(hidden = true) @Context SessionHelper sessionHelper) {
public Response login(@Valid @Parameter(required = true) LoginRequest req,
@Parameter(hidden = true) @Context SessionHelper sessionHelper) {
Optional<User> user = userService.login(req.getName(), req.getPassword());
if (user.isPresent()) {
sessionHelper.setLoggedInUser(user.get());
@@ -265,9 +271,9 @@ public class UserREST {
@Path("/passwordReset")
@POST
@UnitOfWork
@ApiOperation(value = "send a password reset email")
@Operation(summary = "send a password reset email")
@Timed
public Response sendPasswordReset(@Valid @ApiParam(required = true) PasswordResetRequest req) {
public Response sendPasswordReset(@Valid @Parameter(required = true) PasswordResetRequest req) {
User user = userDAO.findByEmail(req.getEmail());
if (user == null) {
return Response.ok().build();
@@ -306,8 +312,8 @@ public class UserREST {
@UnitOfWork
@Produces(MediaType.TEXT_HTML)
@Timed
public Response passwordRecoveryCallback(@ApiParam(required = true) @QueryParam("email") String email,
@ApiParam(required = true) @QueryParam("token") String token) {
public Response passwordRecoveryCallback(@Parameter(required = true) @QueryParam("email") String email,
@Parameter(required = true) @QueryParam("token") String token) {
Preconditions.checkNotNull(email);
Preconditions.checkNotNull(token);
@@ -341,9 +347,9 @@ public class UserREST {
@Path("/profile/deleteAccount")
@POST
@UnitOfWork
@ApiOperation(value = "Delete the user account")
@Operation(summary = "Delete the user account")
@Timed
public Response deleteUser(@ApiParam(hidden = true) @SecurityCheck User user) {
public Response deleteUser(@Parameter(hidden = true) @SecurityCheck User user) {
if (CommaFeedApplication.USERNAME_ADMIN.equals(user.getName()) || CommaFeedApplication.USERNAME_DEMO.equals(user.getName())) {
return Response.status(Status.FORBIDDEN).build();
}