Skip to content

Commit

Permalink
dzikoyskGH-17 Add dashboard view with login component and index with …
Browse files Browse the repository at this point in the history
…auth support
dzikoysk committed Jun 15, 2020
1 parent c6816d2 commit 2e8c466
Showing 23 changed files with 348 additions and 88 deletions.
2 changes: 1 addition & 1 deletion .run/Reposilite.run.xml
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="true" />
<option name="MAIN_CLASS_NAME" value="org.panda_lang.reposilite.Reposilite" />
<module name="reposilite" />
<option name="VM_PARAMETERS" value="-Xmx8M" />
<option name="VM_PARAMETERS" value="-Xmx8M -Dreposilite.debugEnabled=true" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/reposilite-backend/src/test/workspace" />
<extension name="coverage">
<pattern>
Original file line number Diff line number Diff line change
@@ -19,6 +19,7 @@
import io.javalin.Javalin;
import io.javalin.core.JavalinConfig;
import org.eclipse.jetty.server.Server;
import org.panda_lang.reposilite.api.AuthApiController;
import org.panda_lang.reposilite.api.ConfigurationApiController;
import org.panda_lang.reposilite.api.IndexApiController;
import org.panda_lang.reposilite.config.Configuration;
@@ -43,6 +44,7 @@ void start(Configuration configuration, Runnable onStart) {
LookupController lookupController = new LookupController(reposilite.getFrontend(), lookupService);

this.javalin = Javalin.create(config -> config(configuration, config))
.get("/api/auth", new AuthApiController(configuration, reposilite.getAuthenticator()))
.get("/api/configuration", new ConfigurationApiController(reposilite.getConfiguration()))
.get("/api/*", new IndexApiController(reposilite))
.get("/js/app.js", new FrontendController(reposilite))
@@ -61,7 +63,8 @@ private void config(Configuration configuration, JavalinConfig config) {
config.showJavalinBanner = false;

if (configuration.isDebugEnabled()) {
config.enableCorsForOrigin("http://localhost:8080/");
Reposilite.getLogger().info("Debug enabled");
config.enableCorsForAllOrigins();
config.enableDevLogging();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package org.panda_lang.reposilite.api;

import io.javalin.http.Context;
import org.apache.http.HttpStatus;
import org.panda_lang.reposilite.RepositoryController;
import org.panda_lang.reposilite.auth.Authenticator;
import org.panda_lang.reposilite.auth.Session;
import org.panda_lang.reposilite.config.Configuration;

public final class AuthApiController implements RepositoryController {

private final Configuration configuration;
private final Authenticator authenticator;

public AuthApiController(Configuration configuration, Authenticator authenticator) {
this.configuration = configuration;
this.authenticator = authenticator;
}

@Override
public Context handleContext(Context ctx) {
return authenticator
.auth(ctx)
.map(Session::getToken)
.map(token -> new AuthDto(token.getPath(), configuration.getManagers().contains(token.getAlias())))
.map(ctx::json)
.orElseGet(error -> ctx.status(HttpStatus.SC_UNAUTHORIZED).json(new ErrorDto(HttpStatus.SC_UNAUTHORIZED, error)));
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package org.panda_lang.reposilite.api;

import java.io.Serializable;

final class AuthDto implements Serializable {

private final String path;
private final boolean isManager;

AuthDto(String path, boolean isManager) {
this.path = path;
this.isManager = isManager;
}

public boolean isManager() {
return isManager;
}

public String getPath() {
return path;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.panda_lang.reposilite.api;

import io.javalin.http.Context;

final class ErrorUtils {

static Context error(Context context, int status, String message) {
return context.status(status).json(new ErrorDto(status, message));
}

}
Original file line number Diff line number Diff line change
@@ -47,15 +47,10 @@ public IndexApiController(Reposilite reposilite) {
@Override
public Context handleContext(Context ctx) {
Reposilite.getLogger().info(ctx.req.getRequestURI() + " API");
String uri = RepositoryUtils.normalizeUri(configuration, StringUtils.replaceFirst(ctx.req.getRequestURI(), "/api", StringUtils.EMPTY));

if (!configuration.isIndexingEnabled()) {
return ctx.json(new ErrorDto(HttpStatus.SC_LOCKED, "Indexing is disabled"));
}

String uri = RepositoryUtils.normalizeUri(configuration, StringUtils.replaceFirst(ctx.req.getRequestURI(), "/api/", StringUtils.EMPTY));

if (configuration.isFullAuthEnabled() && authenticator.authUri(ctx, uri).getError().isDefined()) {
return ctx.json(new ErrorDto(HttpStatus.SC_UNAUTHORIZED, "Unauthorized request"));
if ((configuration.isFullAuthEnabled() || !configuration.isIndexingEnabled()) && authenticator.authUri(ctx, uri).getError().isDefined()) {
return ErrorUtils.error(ctx, HttpStatus.SC_UNAUTHORIZED, "Unauthorized request");
}

File requestedFile = repositoryService.getFile(uri);
@@ -74,7 +69,7 @@ public Context handleContext(Context ctx) {
}

if (!requestedFile.exists()) {
return ctx.json(new ErrorDto(HttpStatus.SC_NOT_FOUND, "Not Found"));
return ErrorUtils.error(ctx, HttpStatus.SC_NOT_FOUND, "Not Found");
}

if (requestedFile.isFile()) {
Original file line number Diff line number Diff line change
@@ -35,6 +35,10 @@ public Result<Session, String> authDefault(Context context) {
}

public Result<Session, String> authUri(Context context, String uri) {
if (!uri.startsWith("/")) {
uri = "/" + uri;
}

Result<Session, String> authResult = auth(context);

if (authResult.getError().isDefined()) {
Original file line number Diff line number Diff line change
@@ -37,6 +37,7 @@ public final class Configuration implements Serializable {
private boolean rewritePathsEnabled = true;
private boolean fullAuthEnabled = false;
private boolean indexingEnabled = true;
private final List<String> managers = new ArrayList<>(2);

// Frontend properties
private String title = "#onlypanda";
@@ -70,6 +71,9 @@ public final class Configuration implements Serializable {
public void setIndexingEnabled(boolean indexingEnabled) { this.indexingEnabled = indexingEnabled; }
public boolean isIndexingEnabled() { return indexingEnabled; }

public void setManagers(List<String> managers) { this.managers.addAll(managers); }
public List<String> getManagers() { return managers; }

public void setTitle(String title) { this.title = title; }
public String getTitle() { return title; }

Original file line number Diff line number Diff line change
@@ -39,6 +39,10 @@ public Result<V, E> orElse(Function<E, Result<V, E>> orElse) {
return isDefined() ? this : orElse.apply(error);
}

public V orElseGet(Function<E, V> orElse) {
return isDefined() ? value : orElse.apply(error);
}

public boolean isDefined() {
return getValue().isDefined();
}
4 changes: 2 additions & 2 deletions reposilite-backend/src/main/resources/frontend/js/app.js

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions reposilite-backend/src/main/resources/reposilite.yml
Original file line number Diff line number Diff line change
@@ -32,6 +32,10 @@ fullAuthEnabled: false
# If you don't want to display content of your repositories,
# you can just disable indexing
indexingEnabled: true
# List of management tokens used by dashboard to access extra options.
# (By default, people are allowed to use standard dashboard options related to the associated path)
managers: []
# - root

# Title displayed by frontend
title: "#onlypanda"
5 changes: 5 additions & 0 deletions reposilite-backend/src/test/workspace/reposilite.yml
Original file line number Diff line number Diff line change
@@ -6,6 +6,8 @@
hostname: ''
# Port
port: 80
# Debug
debugEnabled: false

# List of supported Maven repositories.
# First directory on the list is the main repository.
@@ -33,6 +35,9 @@ fullAuthEnabled: false
# If you don't want to display content of your repositories,
# you can just disable indexing
indexingEnabled: false
# List of management tokens used by dashboard to access extra options.
# (By default, people are allowed to use standard dashboard options related to the associated path)
managers: []

# Title displayed by frontend
title: "Your company"
40 changes: 2 additions & 38 deletions reposilite-backend/src/test/workspace/stats.yml
Original file line number Diff line number Diff line change
@@ -1,40 +1,4 @@
!!org.panda_lang.reposilite.stats.StatsEntity
"records":
"/releases/org/panda-lang/reposilite/2.10.0-SNAPSHOT/reposilite-2.10.0-SNAPSHOT.pom.md5": !!int "1"
"/releases/org/panda-lang/reposilite/2.10.0-SNAPSHOT/reposilite-2.10.0-SNAPSHOT.jar": !!int "2"
"/api/releases/org/panda-lang/reposilite-parent/2.5.0/maven-metadata.xml": !!int "1"
"/releases/org/panda-lang/reposilite-test/1.0.0-SNAPSHOT/reposilite-test-1.0.0-20200603.224843-1.jar.sha1": !!int "1"
"/api/snapshots/org": !!int "2"
"/api/configuration": !!int "7"
"/api/snapshots": !!int "3"
"/releases/org/panda-lang/reposilite/2.10.0-SNAPSHOT/maven-metadata.xml.sha1": !!int "4"
"/releases/org/panda-lang/reposilite/maven-metadata.xml": !!int "1"
"/releases/org/panda-lang/reposilite-test/1.0.0-SNAPSHOT/maven-metadata.xml.sha1": !!int "1"
"/releases/org/panda-lang/reposilite-test/1.0.0-SNAPSHOT/reposilite-test-1.0.0-20200603.224843-1.pom": !!int "1"
"/api/snapshots/org/panda-lang": !!int "2"
"/favicon.ico": !!int "1"
"/releases/org/panda-lang/reposilite-test/1.0.0-SNAPSHOT/maven-metadata.xml.md5": !!int "1"
"/api/snapshots/org/panda-lang/reposilite-test/1.0.0-SNAPSHOT": !!int "1"
"/releases/org/panda-lang/reposilite-test/1.0.0-SNAPSHOT/maven-metadata.xml": !!int "2"
"/": !!int "2"
"/releases/org/panda-lang/reposilite-test/1.0.0-SNAPSHOT/reposilite-test-1.0.0-20200603.224843-1.jar.md5": !!int "1"
"/snapshots/org/panda-lang/reposilite-test/maven-metadata.xml": !!int "1"
"/releases/org/x": !!int "1"
"/api/": !!int "4"
"/releases/org/panda-lang/reposilite-test/maven-metadata.xml": !!int "3"
"/api/snapshots/org/panda-lang/reposilite-test": !!int "2"
"/releases/org/panda-lang/reposilite-test/1.0.0-SNAPSHOT/reposilite-test-1.0.0-20200603.224843-1.pom.sha1": !!int "1"
"/releases/org/panda-lang/reposilite/2.10.0-SNAPSHOT/reposilite-2.10.0-SNAPSHOT.pom": !!int "1"
"/releases/org/panda-lang/reposilite-test/maven-metadata.xml.md5": !!int "1"
"/api/releases/org/panda-lang/reposilite/2.10.0-SNAPSHOT/maven-metadata.xml": !!int "2"
"/js/app.js": !!int "7"
"/releases/org/panda-lang/reposilite/2.10.0-SNAPSHOT/reposilite-2.10.0-SNAPSHOT.pom.sha1": !!int "1"
"/releases/org/panda-lang/reposilite-test/maven-metadata.xml.sha1": !!int "3"
"/releases/org/panda-lang/reposilite-test/1.0.0-SNAPSHOT/reposilite-test-1.0.0-20200603.224843-1.jar": !!int "1"
"/releases/org/panda-lang/reposilite/2.10.0-SNAPSHOT/maven-metadata.xml": !!int "8"
"/releases/org/panda-lang/reposilite-parent/2.5.0/maven-metadata.xml": !!int "2"
"/releases/org/panda-lang/reposilite-test/1.0.0-SNAPSHOT/reposilite-test-1.0.0-20200603.224843-1.pom.md5": !!int "1"
"/releases/auth/test/test.jar": !!int "5"
"/api/releases/org": !!int "1"
"/api/releases": !!int "1"
"/api/releases/org/x": !!int "1"
"/api/auth": !!int "6"
"/api/": !!int "19"
25 changes: 10 additions & 15 deletions reposilite-frontend/src/components/FileEntry.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<template lang="pug">
.file-preview.w-full
a(v-if="file.type === 'file'" :href="getUri()" target="_blank" )
a(v-if="file.type === 'file'" :href="url()" target="_blank" )
FileEntryContent(:file="file")
router-link(v-else :to="getUri()")
router-link(v-else :to="uri()")
FileEntryContent(:file="file")
</template>

@@ -15,23 +15,18 @@ export default {
FileEntryContent
},
data: () => ({
uri: undefined
qualifier: ''
}),
mounted() {
this.uri = this.$route.params['qualifier']
if (this.uri.length > 0) {
this.uri += '/'
}
this.qualifier = this.getQualifier()
},
methods: {
getUri() {
return '/' + this.uri + this.file.name
uri() {
return this.normalize(this.$route.fullPath) + '/' + this.file.name
},
url() {
return this.qualifier + '/' + this.file.name
}
}
}
</script>

<style lang="stylus">
</style>
</script>
18 changes: 18 additions & 0 deletions reposilite-frontend/src/components/Login.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<template lang="pug">
form#login(v-if="!auth.verified").p-8.text-center(method="post").border-dashed.border-black.border-1.rounded
h1.font-bold.py-4.text-xl Login
div.py-1
input(placeholder="Alias" name="alias" v-model="auth.alias").w-96.p-1
div.py-1
input(placeholder="Token" name="token" v-model="auth.token" autocomple="on").w-96.p-1
div.py-3
button.bg-gray-300.px-6.py-1.mt-1(v-on:click="login") Login
div.py-1
p(v-if="error") {{ this.error }}
</template>

<script>
export default {
}
</script>
13 changes: 8 additions & 5 deletions reposilite-frontend/src/main.js
Original file line number Diff line number Diff line change
@@ -3,17 +3,20 @@ import App from './App.vue'
import Axios from 'axios'
import router from './router'
import './assets/tailwind.css'

import fontawesome from '@fortawesome/fontawesome'
fontawesome.config = { autoReplaceSvg: false }

import Meta from 'vue-meta'
Vue.use(Meta)
import mixins from './mixins'

Vue.config.productionTip = false
Vue.prototype.$http = Axios

fontawesome.config = { autoReplaceSvg: false }

Vue.use(Meta)

Vue.mixin(mixins)

new Vue({
router,
render: h => h(App),
render: h => h(App)
}).$mount('#app')
33 changes: 33 additions & 0 deletions reposilite-frontend/src/mixins.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
const url = ((process.env.NODE_ENV == 'production') ? '/' : 'http://localhost:80/') + 'api';

export default {
methods: {
api(uri, credentials) {
return this.$http.get(url + uri, { auth: credentials })
},
parentPath() {
const elements = ('/' + this.getQualifier()).split('/')
elements.pop()
let path = this.normalize(elements.join('/'))
return path.length == 0 ? '/' : path
},
getQualifier() {
return this.normalize(this.$route.params['qualifier'])
},
normalize(uri) {
if (uri === undefined) {
return '/'
}

if (!uri.startsWith('/')) {
uri = '/' + uri
}

if (uri.length > 1 && uri.endsWith('/')) {
uri = uri.substr(0, uri.length - 1)
}

return uri
}
}
}
Loading

0 comments on commit 2e8c466

Please sign in to comment.