diff --git a/src/main/java/com/artipie/front/Service.java b/src/main/java/com/artipie/front/Service.java index a822907..45afacf 100644 --- a/src/main/java/com/artipie/front/Service.java +++ b/src/main/java/com/artipie/front/Service.java @@ -137,6 +137,21 @@ void start(final int port, final String rest) { ); } ); + this.ignite.path( + "/signout", + () -> { + this.ignite.get( + "", + (req, rsp) -> { + if (req.session() != null) { + req.session().invalidate(); + } + rsp.redirect("/dashboard"); + return "Ok"; + } + ); + } + ); this.ignite.path( "/api", () -> { diff --git a/src/main/java/com/artipie/front/rest/RepositoryService.java b/src/main/java/com/artipie/front/rest/RepositoryService.java index 974f87f..f47c48f 100644 --- a/src/main/java/com/artipie/front/rest/RepositoryService.java +++ b/src/main/java/com/artipie/front/rest/RepositoryService.java @@ -74,6 +74,16 @@ public List list(final String token, final String uname) { * @return Repository content. */ public String repo(final String token, final RepositoryName rname) { + return this.repo(token, rname.toString()); + } + + /** + * Obtain repository content. + * @param token Token. + * @param rname Repository name. + * @return Repository content. + */ + public String repo(final String token, final String rname) { return BaseService.handle( this.httpGet( Optional.of(token), diff --git a/src/main/java/com/artipie/front/rest/SettingsService.java b/src/main/java/com/artipie/front/rest/SettingsService.java index 9c94cc0..a521d8a 100644 --- a/src/main/java/com/artipie/front/rest/SettingsService.java +++ b/src/main/java/com/artipie/front/rest/SettingsService.java @@ -7,6 +7,7 @@ import com.artipie.front.Layout; import java.util.Optional; import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Function; import javax.json.JsonObject; /** @@ -14,16 +15,26 @@ * * @since 1.0 */ +@SuppressWarnings("PMD.AvoidFieldNameMatchingMethodName") public class SettingsService extends BaseService { + /** + * Path to port rest-api. + */ + private static final String PORT_PATH = "/api/v1/settings/port"; + /** * Path to layout rest-api. */ private static final String LAYOUT_PATH = "/api/v1/settings/layout"; + /** + * Port. + */ + private final AtomicReference port; + /** * Layout. */ - @SuppressWarnings("PMD.AvoidFieldNameMatchingMethodName") private final AtomicReference layout; /** @@ -32,24 +43,54 @@ public class SettingsService extends BaseService { */ public SettingsService(final String rest) { super(rest); + this.port = new AtomicReference<>(); this.layout = new AtomicReference<>(); } + /** + * Obtain Artipie server port. + * @return Artipie server port + */ + public int port() { + return this.value( + this.port, + SettingsService.PORT_PATH, + json -> json.getInt("port") + ); + } + /** * Obtain Artipie layout. * @return Artipie layout */ public Layout layout() { - if (this.layout.get() == null) { - final Layout value = BaseService.handle( - this.httpGet(Optional.empty(), SettingsService.LAYOUT_PATH), + return this.value( + this.layout, + SettingsService.LAYOUT_PATH, + json -> Layout.byName(json.getString("layout")) + ); + } + + /** + * Obtain Artipie setting's value. + * @param ref Reference to setting value + * @param path Path to rest service + * @param handler Handler of json content + * @param Resulting type of handler + * @return Artipie layout + */ + private T value(final AtomicReference ref, final String path, + final Function handler) { + if (ref.get() == null) { + final T value = BaseService.handle( + this.httpGet(Optional.empty(), path), res -> { final JsonObject json = BaseService.jsonObject(res); - return Layout.byName(json.getString("layout")); + return handler.apply(json); } ); - this.layout.compareAndSet(null, value); + ref.compareAndSet(null, value); } - return this.layout.get(); + return ref.get(); } } diff --git a/src/main/java/com/artipie/front/ui/repository/RepoList.java b/src/main/java/com/artipie/front/ui/repository/RepoList.java index 7eca2d4..2bed7ad 100644 --- a/src/main/java/com/artipie/front/ui/repository/RepoList.java +++ b/src/main/java/com/artipie/front/ui/repository/RepoList.java @@ -4,13 +4,18 @@ */ package com.artipie.front.ui.repository; +import com.amihaiemil.eoyaml.Yaml; +import com.amihaiemil.eoyaml.YamlMapping; import com.artipie.front.Layout; import com.artipie.front.misc.RouteWrap; import com.artipie.front.rest.RepositoryService; import com.artipie.front.rest.SettingsService; import com.artipie.front.ui.HbPage; +import java.io.IOException; +import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Optional; /** * List of repositories page. @@ -33,12 +38,23 @@ public RepoList(final RepositoryService repository, final SettingsService settin req -> { final String uid = req.session().attribute("uid"); final String token = req.session().attribute("token"); - final List repos; + final List names; if (settings.layout() == Layout.FLAT) { - repos = repository.list(token); + names = repository.list(token); } else { - repos = repository.list(token, uid); + names = repository.list(token, uid); } + final List repos = new ArrayList<>(names.size()); + names.stream().sorted().forEach( + name -> + repos.add( + new Repo( + Integer.toString(settings.port()), + name, + repository.repo(token, name) + ) + ) + ); return Map.of( "title", "Repository list", "repos", repos @@ -47,4 +63,75 @@ public RepoList(final RepositoryService repository, final SettingsService settin ) ); } + + /** + * Repository information. + * @since 0.1.3 + */ + @SuppressWarnings("PMD.AvoidFieldNameMatchingMethodName") + public static class Repo { + /** + * Repository name. + */ + private final String name; + + /** + * Artipie server port. + */ + private final String port; + + /** + * Repository configuration. + */ + private Optional conf; + + /** + * Ctor. + * @param port Artipie's default port + * @param name Name of repository. + * @param conf Repository configuration content + */ + @SuppressWarnings("PMD.ConstructorOnlyInitializesOrCallOtherConstructors") + public Repo(final String port, final String name, final String conf) { + this.port = port; + this.name = name; + try { + this.conf = Optional.of(Yaml.createYamlInput(conf).readYamlMapping()); + } catch (final IOException exc) { + this.conf = Optional.empty(); + } + } + + /** + * Name of repository. + * @return Name of repository. + */ + public String name() { + return this.name; + } + + /** + * Type of repository defined in configuration. + * @return Repository type or empty string + */ + public String type() { + return this.repo().map(repo -> repo.string("type")).orElse(""); + } + + /** + * Port of repository defined in configuration. + * @return Repository port or default Artipie port + */ + public String port() { + return this.repo().map(repo -> repo.string("port")).orElse(this.port); + } + + /** + * Repository repo-section in yaml. + * @return Repository repo-configuration + */ + private Optional repo() { + return this.conf.map(value -> value.yamlMapping("repo")); + } + } } diff --git a/src/main/resources/html/base b/src/main/resources/html/base index 29083ad..fbb1430 100644 --- a/src/main/resources/html/base +++ b/src/main/resources/html/base @@ -7,6 +7,7 @@ + @@ -19,33 +20,34 @@ - - - - - -
- -
-
- {{#block "content"}} - {{/block}} -
-
-
+ + +
  • Sign out
  • + + +
    +
    +
    + {{#block "content"}} + {{/block}} +
    +
    +
    + +