login page in progress

This commit is contained in:
Claude Brisson
2023-12-26 05:59:24 +01:00
parent a13f7510ce
commit 65053e47fc
10 changed files with 119 additions and 96 deletions

View File

@@ -91,6 +91,7 @@
<pairgoth.logger.level>${pairgoth.logger.level}</pairgoth.logger.level>
<pairgoth.logger.format>${pairgoth.logger.format}</pairgoth.logger.format>
<pairgoth.logger.level.org.jeudego.pairgoth.web.ApiServlet.api>debug</pairgoth.logger.level.org.jeudego.pairgoth.web.ApiServlet.api>
<pairgoth.auth>${pairgoth.auth}</pairgoth.auth>
<org.slf4j.simpleLogger.defaultLogLevel>debug</org.slf4j.simpleLogger.defaultLogLevel>
</systemProperties>
<webApp>

View File

@@ -0,0 +1,50 @@
package org.jeudego.pairgoth.web
import javax.servlet.Filter
import javax.servlet.FilterChain
import javax.servlet.FilterConfig
import javax.servlet.RequestDispatcher
import javax.servlet.ServletRequest
import javax.servlet.ServletResponse
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse
import javax.servlet.http.HttpSession
class AuthFilter: Filter {
private lateinit var filterConfig: FilterConfig
protected val defaultRequestDispatcher: RequestDispatcher by lazy {
filterConfig.servletContext.getNamedDispatcher("default")
}
override fun init(filterConfig: FilterConfig) {
this.filterConfig = filterConfig
}
override fun doFilter(req: ServletRequest, resp: ServletResponse, chain: FilterChain) {
val request = req as HttpServletRequest
val response = resp as HttpServletResponse
val uri = request.requestURI
val session: HttpSession? = request.getSession(false)
val auth = WebappManager.getProperty("auth") ?: throw Error("authentication not configured")
if (auth == "none" || whitelist.contains(uri) || uri.contains(Regex("\\.(?!html)")) || session?.getAttribute("logged") != null) {
chain.doFilter(req, resp)
} else {
// TODO - configure if unauth requests are redirected and/or forwarded
// TODO - protection against brute force attacks
if (uri == "/index") {
request.getRequestDispatcher("/index-ffg").forward(req, resp)
} else {
response.sendRedirect("/login")
}
}
}
companion object {
private val whitelist = setOf(
"/index-ffg",
"/login"
)
}
}

View File

@@ -349,4 +349,12 @@
position: sticky;
top: 0;
}
#landing {
text-align: justify;
}
a.disabled {
color: darkgray;
}
}

View File

@@ -19,6 +19,8 @@ api.external.url = http://localhost:8085/api
store = file
store.file.path = tournamentfiles
auth = none
# smtp
smtp.sender =
smtp.host =

View File

@@ -17,6 +17,11 @@
<filter-class>com.republicate.slf4j.impl.IPTagFilter</filter-class>
<async-supported>true</async-supported>
</filter>
<filter>
<filter-name>auth-filter</filter-name>
<filter-class>org.jeudego.pairgoth.web.AuthFilter</filter-class>
<async-supported>true</async-supported>
</filter>
<filter>
<filter-name>dispatching-filter</filter-name>
<filter-class>org.jeudego.pairgoth.web.DispatchingFilter</filter-class>
@@ -35,6 +40,12 @@
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
<filter-mapping>
<filter-name>auth-filter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
<filter-mapping>
<filter-name>dispatching-filter</filter-name>
<url-pattern>/*</url-pattern>

View File

@@ -1,43 +1,39 @@
<div class="section">
<div id="landing" class="section">
<h1>Welcome to <span class="logo">pairgoth</span>, your Go Pairing Engine!</h1>
<h2>What is <span class="logo">pairgoth</span>?</h2>
<p>At its core, <span class="logo">pairgoth</span> is a versatile Go tournament pairing engine designed to make your tournament experience effortless. <span class="logo">pairgoth</span> is the successor of <a href="https://github.com/lucvannier/opengotha">opengotha</a>, the well known pairing system software developed by <a href="http://vannier.info/jeux/accueil.htm">Luc Vannier</a> and uses the same algorithm internally, as well as import and export features towards its format.</p>
<p><span class="logo">pairgoth</span> version 1.0-BETA supports the <b>Swiss</b></a> pairing system, ideal for championships with no handicap games, as well as the <b>MacMahon</b> pairing system, more suited for classical tournaments and cups.</p>
<p>Future versions will support more pairing systems and more features. <a href="mailto:pairgoth@jeudego.org">Your feedback is welcome!</a></p>
<p><span class="logo">pairgoth</span> version 0.1 supports the <b>Swiss</b></a> pairing system, ideal for championships with no handicap games, as well as the <b>MacMahon</b> pairing system, more suited for classical tournaments and cups. It is still in an alpha stage. Future versions will support more pairing systems and more features. <a href="mailto:pairgoth@jeudego.org">Your feedback is most welcome!</a></p>
<h2>How to use <span class="logo">pairgoth</span>?</h2>
<p>We offer you the flexibility to use <span class="logo">pairgoth</span> in a way that best suits your needs. Here are your options:</p>
<ol>
<li>
<p><b>Stay in the browser</b>: If you prefer convenience, you can simply use the <span class="logo">pairgoth</span> instance graciously hosted by the French Go Federation.</p>
<blockquote>
<a class="nobreak" href="https://pairgoth.jeudego.org/menu.html">Launch <span class="logo">pairgoth</span></a>
<a class="nobreak" href="https://pairgoth.jeudego.org/login">Launch <span class="logo">pairgoth</span></a>
</blockquote>
</li>
<li>
<p><b>Launch a standalone instance</b>: This mode allows you to run <span class="logo">pairgoth</span> on your local computer.</p>
<p>That's the best option if you feel more comfortable when running locally or whenever you want to be able to do the pairing without internet. You can choose to use either the standard interface (which is meant to look a lot like opengotha) and the web interface (by launching the engine and connecting to it using a browser).</p>
<blockquote>
<a class="nobreak" href="https://pairgoth.jeudego.org/download.html#standalone">Download <span class="logo">pairgoth</span> standalone</a>
<div><a class="nobreak disabled" #* href="https://pairgoth.jeudego.org/download#standalone" *#>Download <span class="logo">pairgoth</span> standalone, standard interface</a> (not yet available)</div>
<div><a class="nobreak" href="https://pairgoth.jeudego.org/download#standalone">Download <span class="logo">pairgoth</span> standalone, web interface</a> (java required)</div>
<div><a class="nobreak" href="https://pairgoth.jeudego.org/download#standalone">Download <span class="logo">pairgoth</span> standalone, web interface, via docker</a> (docker required)</a></div>
</blockquote>
</li>
<li>
<p><b>Launch a pairing server</b>: This mode is the best suited for big Go events like congresses, it allows to register players, enter results and manage pairing from several workstations at once.</p>
<blockquote>
<a class="nobreak" href="https://pairgoth.jeudego.org/download.html#server">Download <span class="logo">pairgoth</span> client/server</a>
<div>Download the standalone web interface which suits your need, then follow <a class="disabled">the configuration guide</a> (not yet available)</div>
</blockquote>
</li>
<li>
<p><b>Compile from the sources</b>: the <span class="logo">pairgoth</span> project is fully open source, and under the very permissive <a href="https://www.apache.org/licenses/LICENSE-2.0">apache licence</a>, allowing you to tweak it in any possible way. Be sure to contribute back your enhancements!</p>
<p>Since the project is still in alpha, the sources are only available to FFG actors. If that's your case, you can access the sources here:</p>
<blockquote>
<a class="nobreak" href="https://github.com/ffrgo/pairgoth">Browse <span class="logo">pairgoth</span> sources</a>
<!-- <a class="nobreak" href="https://github.com/ffrgo/pairgoth">Browse <span class="logo">pairgoth</span> sources</a> -->
<a class="nobreak" href="https://gitlab.jeudego.org/tournois/pairgoth/">Browse <span class="logo">pairgoth</span> sources on FFG's gitlab</a>
</blockquote>
</li>
</ol>
</div>
<script type="text/javascript">
const lang = '${request.lang}';
// #[[
onLoad(() => {
});
// ]]#
</script>

View File

@@ -0,0 +1,23 @@
<div id="login" class="section">
<form id="login-form" class="ui form">
<div class="field">
<label>Enter the magic word</label>
<input type="text" name="sesame"/>
<button type="submit" class="ui green floating button">Log in</button>
</div>
</form>
</div>
<script type="text/javascript">
onLoad(()=>{
$('#login-form').on('submit', e => {
api.postJson('login', { sesame: $('input[name="sesame"]').val() })
.then(resp => {
if (resp !== 'error') {
document.location.href = '/index'
}
});
e.preventDefault();
return false;
});
});
</script>