Merge remote-tracking branch 'origin/stable' into develop
Conflicts: documentation/developer/jmeter-main-test-plan.png documentation/developer/metrics-visualvm-screenshot.png
This commit is contained in:
@@ -22,9 +22,9 @@ package org.libresonic.player.controller;
|
||||
import org.libresonic.player.domain.MediaFile;
|
||||
import org.libresonic.player.domain.PlayQueue;
|
||||
import org.libresonic.player.domain.Player;
|
||||
import org.libresonic.player.service.JWTSecurityService;
|
||||
import org.libresonic.player.service.NetworkService;
|
||||
import org.libresonic.player.service.PlayerService;
|
||||
import org.libresonic.player.service.SettingsService;
|
||||
import org.libresonic.player.service.TranscodingService;
|
||||
import org.libresonic.player.util.StringUtil;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -32,6 +32,7 @@ import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
@@ -52,9 +53,9 @@ public class M3UController {
|
||||
@Autowired
|
||||
private PlayerService playerService;
|
||||
@Autowired
|
||||
private SettingsService settingsService;
|
||||
@Autowired
|
||||
private TranscodingService transcodingService;
|
||||
@Autowired
|
||||
private JWTSecurityService jwtSecurityService;
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET)
|
||||
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
|
||||
@@ -89,7 +90,12 @@ public class M3UController {
|
||||
duration = -1;
|
||||
}
|
||||
out.println("#EXTINF:" + duration + "," + mediaFile.getArtist() + " - " + mediaFile.getTitle());
|
||||
out.println(url + "player=" + player.getId() + "&id=" + mediaFile.getId() + "&suffix=." + transcodingService.getSuffix(player, mediaFile, null));
|
||||
|
||||
String urlNoAuth = url + "player=" + player.getId() + "&id=" + mediaFile.getId() + "&suffix=." +
|
||||
transcodingService.getSuffix(player, mediaFile, null);
|
||||
String urlWithAuth = jwtSecurityService.addJWTToken(UriComponentsBuilder.fromUriString(urlNoAuth)).build().toUriString();
|
||||
out.println(urlWithAuth);
|
||||
out.println();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ public class RatingDao extends AbstractDao {
|
||||
|
||||
String sql = "select user_rating.path from user_rating, media_file " +
|
||||
"where user_rating.path=media_file.path and media_file.present and media_file.type = :type and media_file.folder in (:folders) " +
|
||||
"group by path " +
|
||||
"group by user_rating.path " +
|
||||
"order by avg(rating) desc limit :count offset :offset";
|
||||
return namedQueryForStrings(sql, args);
|
||||
}
|
||||
|
||||
+14
-14
@@ -94,7 +94,7 @@ public class GlobalSecurityConfig extends GlobalAuthenticationConfigurerAdapter
|
||||
.csrf().requireCsrfProtectionMatcher(csrfSecurityRequestMatcher).and()
|
||||
.headers().frameOptions().sameOrigin().and()
|
||||
.authorizeRequests()
|
||||
.antMatchers("/ext/stream/**", "/ext/coverArt.view", "/ext/share/**", "/ext/hls/**")
|
||||
.antMatchers("/ext/stream/**", "/ext/coverArt*", "/ext/share/**", "/ext/hls/**")
|
||||
.hasAnyRole("TEMP", "USER").and()
|
||||
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
|
||||
.exceptionHandling().and()
|
||||
@@ -125,29 +125,29 @@ public class GlobalSecurityConfig extends GlobalAuthenticationConfigurerAdapter
|
||||
.frameOptions()
|
||||
.sameOrigin()
|
||||
.and().authorizeRequests()
|
||||
.antMatchers("/recover.view", "/accessDenied.view",
|
||||
.antMatchers("/recover*", "/accessDenied*",
|
||||
"/style/**", "/icons/**", "/flash/**", "/script/**",
|
||||
"/sonos/**", "/crossdomain.xml", "/login", "/error")
|
||||
.permitAll()
|
||||
.antMatchers("/personalSettings.view", "/passwordSettings.view",
|
||||
"/playerSettings.view", "/shareSettings.view", "/passwordSettings.view")
|
||||
.antMatchers("/personalSettings*", "/passwordSettings*",
|
||||
"/playerSettings*", "/shareSettings*", "/passwordSettings*")
|
||||
.hasRole("SETTINGS")
|
||||
.antMatchers("/generalSettings.view", "/advancedSettings.view", "/userSettings.view",
|
||||
"/musicFolderSettings.view", "/databaseSettings.view")
|
||||
.antMatchers("/generalSettings*", "/advancedSettings*", "/userSettings*",
|
||||
"/musicFolderSettings*", "/databaseSettings*")
|
||||
.hasRole("ADMIN")
|
||||
.antMatchers("/deletePlaylist.view", "/savePlaylist.view")
|
||||
.antMatchers("/deletePlaylist*", "/savePlaylist*", "/db*")
|
||||
.hasRole("PLAYLIST")
|
||||
.antMatchers("/download.view")
|
||||
.antMatchers("/download*")
|
||||
.hasRole("DOWNLOAD")
|
||||
.antMatchers("/upload.view")
|
||||
.antMatchers("/upload*")
|
||||
.hasRole("UPLOAD")
|
||||
.antMatchers("/createShare.view")
|
||||
.antMatchers("/createShare*")
|
||||
.hasRole("SHARE")
|
||||
.antMatchers("/changeCoverArt.view", "/editTags.view")
|
||||
.antMatchers("/changeCoverArt*", "/editTags*")
|
||||
.hasRole("COVERART")
|
||||
.antMatchers("/setMusicFileInfo.view")
|
||||
.antMatchers("/setMusicFileInfo*")
|
||||
.hasRole("COMMENT")
|
||||
.antMatchers("/podcastReceiverAdmin.view")
|
||||
.antMatchers("/podcastReceiverAdmin*")
|
||||
.hasRole("PODCAST")
|
||||
.antMatchers("/**")
|
||||
.hasRole("USER")
|
||||
@@ -155,7 +155,7 @@ public class GlobalSecurityConfig extends GlobalAuthenticationConfigurerAdapter
|
||||
.and().formLogin()
|
||||
.loginPage("/login")
|
||||
.permitAll()
|
||||
.defaultSuccessUrl("/index.view", true)
|
||||
.defaultSuccessUrl("/index", true)
|
||||
.failureUrl(FAILURE_URL)
|
||||
.usernameParameter("j_username")
|
||||
.passwordParameter("j_password")
|
||||
|
||||
@@ -61,8 +61,21 @@ public class NetworkService {
|
||||
|
||||
private static URI calculateProxyUri(HttpServletRequest request) throws URISyntaxException {
|
||||
String xForardedHost = request.getHeader(X_FORWARDED_HOST);
|
||||
// If the request has been through multiple reverse proxies,
|
||||
// We need to return the original Host that the client used
|
||||
if (xForardedHost != null) {
|
||||
xForardedHost = xForardedHost.split(",")[0];
|
||||
}
|
||||
|
||||
if(!isValidXForwardedHost(xForardedHost)) {
|
||||
xForardedHost = request.getHeader(X_FORWARDED_SERVER);
|
||||
|
||||
// If the request has been through multiple reverse proxies,
|
||||
// We need to return the original Host that the client used
|
||||
if (xForardedHost != null) {
|
||||
xForardedHost = xForardedHost.split(",")[0];
|
||||
}
|
||||
|
||||
if(!isValidXForwardedHost(xForardedHost)) {
|
||||
throw new RuntimeException("Cannot calculate proxy uri without HTTP header " + X_FORWARDED_HOST);
|
||||
}
|
||||
@@ -72,6 +85,9 @@ public class NetworkService {
|
||||
String host = proxyHost.getHost();
|
||||
int port = proxyHost.getPort();
|
||||
String scheme = request.getHeader(X_FORWARDED_PROTO);
|
||||
if(StringUtils.isBlank(scheme)) {
|
||||
throw new RuntimeException("Scheme not provided");
|
||||
}
|
||||
|
||||
return new URI(scheme, null, host, port, urlPathHelper.getContextPath(request), null, null);
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
</changeSet>
|
||||
<changeSet id="schema52_002" author="muff1nman">
|
||||
<validCheckSum>7:8fde86035edbca443a54b1861ae70819</validCheckSum>
|
||||
<validCheckSum>7:e7e0f04cd4691ec2b5d955b449e0154b</validCheckSum>
|
||||
<preConditions onFail="MARK_RAN">
|
||||
<not>
|
||||
<tableExists tableName="music_folder_user" />
|
||||
|
||||
+3
-2
@@ -317,6 +317,7 @@ advancedsettings.ldapsearchfilter = LDAP Suchfilter
|
||||
advancedsettings.ldapmanagerdn = LDAP Manager DN<br><div class="detail">(Optional)</div>
|
||||
advancedsettings.ldapmanagerpassword = Passwort
|
||||
advancedsettings.ldapautoshadowing = Automatische Erstellung von Benutzern in {0}
|
||||
advancedsettings.ldapRequiresRestart = \u00C4nderungen an den LDAP Einstellungen erfordern einen Neustart
|
||||
|
||||
# personalSettings.jsp
|
||||
personalsettings.title = Layout Einstellungen f\u00FCr {0}
|
||||
@@ -409,7 +410,7 @@ transcodingsettings.info = <p class="Detail">(%s = Die Datei die transcodiert wi
|
||||
Festplattenspeicher.<p/> \
|
||||
<p>Das Transcoding wird von Drittanbieter-Kommandozeilenprogrammen \u00FCbernommen, welche in {0} installiert sein m\u00FCssen. \
|
||||
Mehr \u00FCber das Transcoding erf\u00E4hrst du \
|
||||
hier <a target="_blank" href="http://libresonic.org/pages/transcoding.jsp"><b>hier</b></a>. Du kannst deinen eigenen Transcoder verwenden, wenn er \
|
||||
hier <a target="_blank" href="http://libresonic.github.io/wiki/transcode/"><b>hier</b></a>. Du kannst deinen eigenen Transcoder verwenden, wenn er \
|
||||
folgende Funktionen erf\u00FCllt: \
|
||||
<ul> \
|
||||
<li>Er muss ein Kommandozeilen-Interface haben.</li> \
|
||||
@@ -636,7 +637,7 @@ podcastreceiver.status.deleted = Gel\u00F6scht
|
||||
podcastreceiver.status.skipped = Abgebrochen
|
||||
podcastreceiver.downloadselected= Ausgew\u00E4hlte downloaden
|
||||
podcastreceiver.deleteselected= L\u00F6sche ausgew\u00E4hlte
|
||||
podcastreceiver.confirmdelete= Ausgew\u00C4hlte Podcasts wirklich l\u00F6schen?
|
||||
podcastreceiver.confirmdelete= Ausgew\u00E4hlte Podcasts wirklich l\u00F6schen?
|
||||
podcastreceiver.check = Suche nach neuen Episoden
|
||||
podcastreceiver.refresh = Seite neu laden
|
||||
podcastreceiver.settings = Podcast Einstellungen
|
||||
|
||||
Reference in New Issue
Block a user