Merge branch 'develop' into biconou_develop_PR_metrics
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
package org.libresonic.player.boot;
|
||||
|
||||
import net.sf.ehcache.constructs.web.ShutdownListener;
|
||||
import org.apache.catalina.Container;
|
||||
import org.apache.catalina.Wrapper;
|
||||
import org.apache.catalina.webresources.StandardRoot;
|
||||
import org.directwebremoting.servlet.DwrServlet;
|
||||
import org.libresonic.player.filter.*;
|
||||
import org.libresonic.player.spring.LibresonicPropertySourceConfigurer;
|
||||
@@ -11,6 +14,10 @@ import org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration
|
||||
import org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
|
||||
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
|
||||
import org.springframework.boot.context.embedded.tomcat.TomcatContextCustomizer;
|
||||
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
|
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||
import org.springframework.boot.web.servlet.ServletRegistrationBean;
|
||||
import org.springframework.boot.web.support.SpringBootServletInitializer;
|
||||
@@ -32,7 +39,7 @@ import javax.servlet.ServletContextListener;
|
||||
"classpath:/applicationContext-cache.xml",
|
||||
"classpath:/applicationContext-sonos.xml",
|
||||
"classpath:/libresonic-servlet.xml"})
|
||||
public class Application extends SpringBootServletInitializer {
|
||||
public class Application extends SpringBootServletInitializer implements EmbeddedServletContainerCustomizer {
|
||||
|
||||
/**
|
||||
* Registers the DWR servlet.
|
||||
@@ -177,9 +184,36 @@ public class Application extends SpringBootServletInitializer {
|
||||
return doConfigure(application);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void customize(ConfigurableEmbeddedServletContainer container) {
|
||||
if (container instanceof TomcatEmbeddedServletContainerFactory) {
|
||||
TomcatEmbeddedServletContainerFactory tomcatFactory = (TomcatEmbeddedServletContainerFactory) container;
|
||||
tomcatFactory.addContextCustomizers((TomcatContextCustomizer) context -> {
|
||||
|
||||
// Increase the size and time before eviction of the Tomcat
|
||||
// cache so that resources aren't uncompressed too often.
|
||||
// See https://github.com/jhipster/generator-jhipster/issues/3995
|
||||
StandardRoot resources = new StandardRoot();
|
||||
resources.setCacheMaxSize(100000);
|
||||
resources.setCacheObjectMaxSize(4000);
|
||||
resources.setCacheTtl(24 * 3600 * 1000); // 1 day, in milliseconds
|
||||
context.setResources(resources);
|
||||
|
||||
// Put Jasper in production mode so that JSP aren't recompiled
|
||||
// on each request.
|
||||
// See http://stackoverflow.com/questions/29653326/spring-boot-application-slow-because-of-jsp-compilation
|
||||
Container jsp = context.findChild("jsp");
|
||||
if (jsp instanceof Wrapper) {
|
||||
((Wrapper)jsp).addInitParameter("development", "false");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplicationBuilder builder = new SpringApplicationBuilder();
|
||||
doConfigure(builder).run(args);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+2
@@ -98,6 +98,8 @@ public class AdvancedSettingsController {
|
||||
settingsService.setSmtpPassword(command.getSmtpPassword());
|
||||
}
|
||||
|
||||
settingsService.save();
|
||||
|
||||
return "redirect:advancedSettings.view";
|
||||
}
|
||||
|
||||
|
||||
@@ -1,35 +1,9 @@
|
||||
package org.libresonic.player.controller;
|
||||
|
||||
import org.apache.commons.lang.ObjectUtils;
|
||||
import org.libresonic.player.service.SettingsService;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* This class has been created to refactor code previously present
|
||||
* in the MultiController.
|
||||
*/
|
||||
public class ControllerUtils {
|
||||
|
||||
public static void updatePortAndContextPath(HttpServletRequest request, SettingsService settingsService) {
|
||||
|
||||
int port = Integer.parseInt(System.getProperty("libresonic.port", String.valueOf(request.getLocalPort())));
|
||||
int httpsPort = Integer.parseInt(System.getProperty("libresonic.httpsPort", "0"));
|
||||
|
||||
String contextPath = request.getContextPath().replace("/", "");
|
||||
|
||||
if (settingsService.getPort() != port) {
|
||||
settingsService.setPort(port);
|
||||
settingsService.save();
|
||||
}
|
||||
if (settingsService.getHttpsPort() != httpsPort) {
|
||||
settingsService.setHttpsPort(httpsPort);
|
||||
settingsService.save();
|
||||
}
|
||||
if (!ObjectUtils.equals(settingsService.getUrlRedirectContextPath(), contextPath)) {
|
||||
settingsService.setUrlRedirectContextPath(contextPath);
|
||||
settingsService.save();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ public class DBController {
|
||||
@Autowired
|
||||
private DaoHelper daoHelper;
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET)
|
||||
@RequestMapping(method = { RequestMethod.GET, RequestMethod.POST })
|
||||
protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception {
|
||||
Map<String, Object> map = new HashMap<String, Object>();
|
||||
|
||||
|
||||
-1
@@ -41,7 +41,6 @@ public class GettingStartedController {
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET)
|
||||
public ModelAndView gettingStarted(HttpServletRequest request) {
|
||||
ControllerUtils.updatePortAndContextPath(request,settingsService);
|
||||
|
||||
if (request.getParameter("hide") != null) {
|
||||
settingsService.setGettingStartedEnabled(false);
|
||||
|
||||
@@ -29,7 +29,6 @@ public class IndexController {
|
||||
|
||||
@RequestMapping(method = { RequestMethod.GET})
|
||||
public ModelAndView index(HttpServletRequest request) {
|
||||
ControllerUtils.updatePortAndContextPath(request,settingsService);
|
||||
UserSettings userSettings = settingsService.getUserSettings(securityService.getCurrentUsername(request));
|
||||
|
||||
Map<String, Object> map = new HashMap<String, Object>();
|
||||
|
||||
+1
-1
@@ -80,7 +80,7 @@ public class StatusController {
|
||||
}
|
||||
|
||||
|
||||
private static class TransferStatusHolder {
|
||||
public static class TransferStatusHolder {
|
||||
private TransferStatus transferStatus;
|
||||
private boolean isStream;
|
||||
private boolean isDownload;
|
||||
|
||||
@@ -69,11 +69,23 @@ public class UserDao extends AbstractDao {
|
||||
* Returns the user with the given username.
|
||||
*
|
||||
* @param username The username used when logging in.
|
||||
* @param caseSensitive
|
||||
* @return The user, or <code>null</code> if not found.
|
||||
*/
|
||||
public User getUserByName(String username) {
|
||||
String sql = "select " + USER_COLUMNS + " from " + getUserTable() + " where username=?";
|
||||
User user = queryOne(sql, userRowMapper, username);
|
||||
public User getUserByName(String username, boolean caseSensitive) {
|
||||
String sql;
|
||||
if(caseSensitive) {
|
||||
sql = "select " + USER_COLUMNS + " from " + getUserTable() + " where username=?";
|
||||
} else {
|
||||
sql = "select " + USER_COLUMNS + " from " + getUserTable() + " where UPPER(username)=UPPER(?)";
|
||||
}
|
||||
List<User> users = query(sql, userRowMapper, username);
|
||||
User user = null;
|
||||
if(users.size() == 1) {
|
||||
user = users.iterator().next();
|
||||
} else if (users.size() > 1) {
|
||||
throw new RuntimeException("Too many matching users");
|
||||
}
|
||||
if(user != null) {
|
||||
readRoles(user);
|
||||
}
|
||||
|
||||
+133
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.libresonic.player.security;
|
||||
|
||||
import org.libresonic.player.Logger;
|
||||
import org.libresonic.player.domain.User;
|
||||
import org.libresonic.player.service.SecurityService;
|
||||
import org.libresonic.player.service.SettingsService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.ldap.core.DirContextAdapter;
|
||||
import org.springframework.ldap.core.DirContextOperations;
|
||||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.ldap.ppolicy.PasswordPolicyControl;
|
||||
import org.springframework.security.ldap.ppolicy.PasswordPolicyResponseControl;
|
||||
import org.springframework.security.ldap.userdetails.LdapUserDetailsImpl;
|
||||
import org.springframework.security.ldap.userdetails.UserDetailsContextMapper;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
@Component
|
||||
public class LibresonicUserDetailsContextMapper implements UserDetailsContextMapper {
|
||||
// ~ Instance fields
|
||||
// ================================================================================================
|
||||
|
||||
private final Logger logger = Logger.getLogger(LibresonicUserDetailsContextMapper.class);
|
||||
private String passwordAttributeName = "userPassword";
|
||||
|
||||
@Autowired
|
||||
SecurityService securityService;
|
||||
|
||||
@Autowired
|
||||
SettingsService settingsService;
|
||||
|
||||
// ~ Methods
|
||||
// ========================================================================================================
|
||||
|
||||
public UserDetails mapUserFromContext(DirContextOperations ctx, String username,
|
||||
Collection<? extends GrantedAuthority> authorities) {
|
||||
String dn = ctx.getNameInNamespace();
|
||||
|
||||
logger.debug("Mapping user details from context with DN: " + dn);
|
||||
|
||||
// User must be defined in Libresonic, unless auto-shadowing is enabled.
|
||||
User user = securityService.getUserByName(username, false);
|
||||
if (user == null && !settingsService.isLdapAutoShadowing()) {
|
||||
throw new BadCredentialsException("User does not exist.");
|
||||
}
|
||||
|
||||
if (user == null) {
|
||||
User newUser = new User(username, "", null, true, 0L, 0L, 0L);
|
||||
newUser.setStreamRole(true);
|
||||
newUser.setSettingsRole(true);
|
||||
securityService.createUser(newUser);
|
||||
logger.info("Created local user '" + username + "' for DN " + dn);
|
||||
user = securityService.getUserByName(username, false);
|
||||
}
|
||||
|
||||
// LDAP authentication must be enabled for the given user.
|
||||
if (!user.isLdapAuthenticated()) {
|
||||
throw new BadCredentialsException("LDAP authentication disabled for user.");
|
||||
}
|
||||
|
||||
LdapUserDetailsImpl.Essence essence = new LdapUserDetailsImpl.Essence();
|
||||
essence.setDn(dn);
|
||||
|
||||
Object passwordValue = ctx.getObjectAttribute(passwordAttributeName);
|
||||
|
||||
if (passwordValue != null) {
|
||||
essence.setPassword(mapPassword(passwordValue));
|
||||
}
|
||||
|
||||
essence.setUsername(user.getUsername());
|
||||
|
||||
// Add the supplied authorities
|
||||
for (GrantedAuthority authority : securityService.getGrantedAuthorities(user.getUsername())) {
|
||||
essence.addAuthority(authority);
|
||||
}
|
||||
|
||||
// Check for PPolicy data
|
||||
|
||||
PasswordPolicyResponseControl ppolicy = (PasswordPolicyResponseControl) ctx
|
||||
.getObjectAttribute(PasswordPolicyControl.OID);
|
||||
|
||||
if (ppolicy != null) {
|
||||
essence.setTimeBeforeExpiration(ppolicy.getTimeBeforeExpiration());
|
||||
essence.setGraceLoginsRemaining(ppolicy.getGraceLoginsRemaining());
|
||||
}
|
||||
|
||||
return essence.createUserDetails();
|
||||
|
||||
}
|
||||
|
||||
public void mapUserToContext(UserDetails user, DirContextAdapter ctx) {
|
||||
throw new UnsupportedOperationException(
|
||||
"LdapUserDetailsMapper only supports reading from a context. Please"
|
||||
+ "use a subclass if mapUserToContext() is required.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Extension point to allow customized creation of the user's password from the
|
||||
* attribute stored in the directory.
|
||||
*
|
||||
* @param passwordValue the value of the password attribute
|
||||
* @return a String representation of the password.
|
||||
*/
|
||||
protected String mapPassword(Object passwordValue) {
|
||||
|
||||
if (!(passwordValue instanceof String)) {
|
||||
// Assume it's binary
|
||||
passwordValue = new String((byte[]) passwordValue);
|
||||
}
|
||||
|
||||
return (String) passwordValue;
|
||||
|
||||
}
|
||||
}
|
||||
+20
-3
@@ -1,6 +1,7 @@
|
||||
package org.libresonic.player.security;
|
||||
|
||||
import org.libresonic.player.service.SecurityService;
|
||||
import org.libresonic.player.service.SettingsService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@@ -18,20 +19,37 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Autowired
|
||||
private SecurityService securityService;
|
||||
|
||||
@Autowired
|
||||
private CsrfSecurityRequestMatcher csrfSecurityRequestMatcher;
|
||||
|
||||
@Autowired
|
||||
LoginFailureLogger loginFailureLogger;
|
||||
|
||||
@Autowired
|
||||
SettingsService settingsService;
|
||||
|
||||
@Autowired
|
||||
LibresonicUserDetailsContextMapper libresonicUserDetailsContextMapper;
|
||||
|
||||
@Override
|
||||
@Bean(name = "authenticationManager")
|
||||
public AuthenticationManager authenticationManagerBean() throws Exception {
|
||||
return super.authenticationManagerBean();
|
||||
}
|
||||
|
||||
|
||||
@Autowired
|
||||
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
|
||||
if (settingsService.isLdapEnabled()) {
|
||||
auth.ldapAuthentication()
|
||||
.contextSource()
|
||||
.managerDn(settingsService.getLdapManagerDn())
|
||||
.managerPassword(settingsService.getLdapManagerPassword())
|
||||
.url(settingsService.getLdapUrl())
|
||||
.and()
|
||||
.userSearchFilter(settingsService.getLdapSearchFilter())
|
||||
.userDetailsContextMapper(libresonicUserDetailsContextMapper);
|
||||
}
|
||||
auth.userDetailsService(securityService);
|
||||
}
|
||||
|
||||
@@ -89,7 +107,6 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
.passwordParameter("j_password")
|
||||
// see http://docs.spring.io/spring-security/site/docs/3.2.4.RELEASE/reference/htmlsingle/#csrf-logout
|
||||
.and().logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout", "GET")).logoutSuccessUrl("/login?logout")
|
||||
.and().rememberMe().userDetailsService(securityService).key("libresonic");
|
||||
|
||||
.and().rememberMe().key("libresonic");
|
||||
}
|
||||
}
|
||||
@@ -461,8 +461,7 @@ public class PlaylistService {
|
||||
for (Object obj : tracks) {
|
||||
Element track = (Element) obj;
|
||||
String location = track.getChildText("location", ns);
|
||||
if (location != null && location.startsWith("file://")) {
|
||||
location = location.replaceFirst("file://", "");
|
||||
if (location != null) {
|
||||
MediaFile file = getMediaFile(location);
|
||||
if (file != null) {
|
||||
ok.add(file);
|
||||
|
||||
@@ -62,11 +62,22 @@ public class SecurityService implements UserDetailsService {
|
||||
* @throws DataAccessException If user could not be found for a repository-specific reason.
|
||||
*/
|
||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
|
||||
User user = getUserByName(username);
|
||||
return loadUserByUsername(username, true);
|
||||
}
|
||||
|
||||
public UserDetails loadUserByUsername(String username, boolean caseSensitive)
|
||||
throws UsernameNotFoundException, DataAccessException {
|
||||
User user = getUserByName(username, caseSensitive);
|
||||
if (user == null) {
|
||||
throw new UsernameNotFoundException("User \"" + username + "\" was not found.");
|
||||
}
|
||||
|
||||
List<GrantedAuthority> authorities = getGrantedAuthorities(username);
|
||||
|
||||
return new org.springframework.security.core.userdetails.User(username, user.getPassword(), authorities);
|
||||
}
|
||||
|
||||
public List<GrantedAuthority> getGrantedAuthorities(String username) {
|
||||
String[] roles = userDao.getRolesForUser(username);
|
||||
List<GrantedAuthority> authorities = new ArrayList<>();
|
||||
authorities.add(new SimpleGrantedAuthority("IS_AUTHENTICATED_ANONYMOUSLY"));
|
||||
@@ -74,8 +85,7 @@ public class SecurityService implements UserDetailsService {
|
||||
for (int i = 0; i < roles.length; i++) {
|
||||
authorities.add(new SimpleGrantedAuthority("ROLE_" + roles[i].toUpperCase()));
|
||||
}
|
||||
|
||||
return new org.springframework.security.core.userdetails.User(username, user.getPassword(), authorities);
|
||||
return authorities;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -86,7 +96,7 @@ public class SecurityService implements UserDetailsService {
|
||||
*/
|
||||
public User getCurrentUser(HttpServletRequest request) {
|
||||
String username = getCurrentUsername(request);
|
||||
return username == null ? null : userDao.getUserByName(username);
|
||||
return username == null ? null : getUserByName(username);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -106,7 +116,17 @@ public class SecurityService implements UserDetailsService {
|
||||
* @return The user, or <code>null</code> if not found.
|
||||
*/
|
||||
public User getUserByName(String username) {
|
||||
return userDao.getUserByName(username);
|
||||
return getUserByName(username, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the user with the given username
|
||||
* @param username
|
||||
* @param caseSensitive If false, will do a case insensitive search
|
||||
* @return
|
||||
*/
|
||||
public User getUserByName(String username, boolean caseSensitive) {
|
||||
return userDao.getUserByName(username, caseSensitive);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+1
@@ -371,6 +371,7 @@ advancedsettings.ldapsearchfilter = LDAP search filter
|
||||
advancedsettings.ldapmanagerdn = LDAP manager DN<br><div class="detail">(Optional)</div>
|
||||
advancedsettings.ldapmanagerpassword = Password
|
||||
advancedsettings.ldapautoshadowing = Automatically create users in {0}
|
||||
advancedsettings.ldapRequiresRestart = LDAP settings require a restart to take effect
|
||||
advancedsettings.smtpPort = SMTP port
|
||||
advancedsettings.smtpServer = SMTP server
|
||||
advancedsettings.smtpEncryption = SMTP encryption
|
||||
|
||||
@@ -138,6 +138,8 @@
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p class="warning"><fmt:message key="advancedsettings.ldapRequiresRestart"/></p>
|
||||
|
||||
<input type="submit" value="<fmt:message key="common.save"/>" style="margin-right:0.3em">
|
||||
<input type="button" value="<fmt:message key="common.cancel"/>" onclick="location.href='nowPlaying.view'">
|
||||
|
||||
|
||||
@@ -278,6 +278,7 @@
|
||||
|
||||
<div id="commentForm" style="display:none">
|
||||
<form method="post" action="setMusicFileInfo.view">
|
||||
<sec:csrfInput />
|
||||
<input type="hidden" name="action" value="comment">
|
||||
<input type="hidden" name="id" value="${model.dir.id}">
|
||||
<textarea name="comment" rows="6" cols="70">${model.dir.comment}</textarea>
|
||||
|
||||
@@ -208,6 +208,7 @@
|
||||
|
||||
<div id="commentForm" style="display:none">
|
||||
<form method="post" action="setMusicFileInfo.view">
|
||||
<sec:csrfInput />
|
||||
<input type="hidden" name="action" value="comment">
|
||||
<input type="hidden" name="id" value="${model.dir.id}">
|
||||
<textarea name="comment" rows="6" cols="70">${model.dir.comment}</textarea>
|
||||
|
||||
@@ -91,6 +91,7 @@
|
||||
<body class="mainframe bgcolor1" onload="search()">
|
||||
<h1><fmt:message key="changecoverart.title"/></h1>
|
||||
<form action="javascript:search()">
|
||||
<sec:csrfInput />
|
||||
<table class="indent"><tr>
|
||||
<td><input id="artist" name="artist" placeholder="<fmt:message key="changecoverart.artist"/>" size="35" type="text" value="${model.artist}" onclick="select()"/></td>
|
||||
<td><input id="album" name="album" placeholder="<fmt:message key="changecoverart.album"/>" size="35" type="text" value="${model.album}" onclick="select()"/></td>
|
||||
@@ -99,6 +100,7 @@
|
||||
</form>
|
||||
|
||||
<form action="javascript:setImage(dwr.util.getValue('url'))">
|
||||
<sec:csrfInput />
|
||||
<table><tr>
|
||||
<td><label for="url"><fmt:message key="changecoverart.address"/></label></td>
|
||||
<td style="padding-left:0.5em"><input type="text" name="url" size="50" id="url" value="http://" onclick="select()"/></td>
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
<h1>Database query</h1>
|
||||
|
||||
<form method="post" action="db.view">
|
||||
<sec:csrfInput />
|
||||
<textarea rows="10" cols="80" id="query" name="query" style="margin-top:1em">${model.query}</textarea>
|
||||
<input type="submit" value="<fmt:message key="common.ok"/>">
|
||||
</form>
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
</c:import>
|
||||
|
||||
<form method="post" action="dlnaSettings.view">
|
||||
<sec:csrfInput />
|
||||
|
||||
<div>
|
||||
<input type="checkbox" name="dlnaEnabled" id="dlnaEnabled" class="checkbox"
|
||||
|
||||
@@ -31,6 +31,16 @@
|
||||
%>
|
||||
|
||||
<table class="ruleTable indent">
|
||||
<tr><td class="ruleTableHeader">Status</td>
|
||||
<td class="ruleTableCell"><c:out value="${status}" /></td></tr>
|
||||
<tr><td class="ruleTableHeader">Error</td>
|
||||
<td class="ruleTableCell"><c:out value="${error}" /></td></tr>
|
||||
<tr><td class="ruleTableHeader">Message</td>
|
||||
<td class="ruleTableCell"><c:out value="${message}" /></td></tr>
|
||||
<tr><td class="ruleTableHeader">Path</td>
|
||||
<td class="ruleTableCell"><c:out value="${path}" /></td></tr>
|
||||
<tr><td class="ruleTableHeader">Time</td>
|
||||
<td class="ruleTableCell"><c:out value="${timestamp}" /></td></tr>
|
||||
<tr><td class="ruleTableHeader">Exception</td>
|
||||
<td class="ruleTableCell"><c:out value="${exception}" /></td></tr>
|
||||
<tr><td class="ruleTableHeader">Java version</td>
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
<fmt:message key="importPlaylist.text"/>
|
||||
</div>
|
||||
<form method="post" enctype="multipart/form-data" action="importPlaylist.view">
|
||||
<sec:csrfInput />
|
||||
<input type="file" id="file" name="file" size="40"/>
|
||||
<input type="submit" value="<fmt:message key="common.ok"/>"/>
|
||||
</form>
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
</c:import>
|
||||
|
||||
<form method="post" action="internetRadioSettings.view">
|
||||
<sec:csrfInput />
|
||||
<table class="indent">
|
||||
<tr>
|
||||
<th><fmt:message key="internetradiosettings.name"/></th>
|
||||
|
||||
@@ -62,6 +62,7 @@
|
||||
} catch(e) { return; }
|
||||
elements = form.getElementsByTagName("input");
|
||||
for (var i = 0; i < elements.length; i++) {
|
||||
if (elements[i].type == "hidden") continue;
|
||||
if (elements[i].type == "submit") continue;
|
||||
if (data[elements[i].name]) elements[i].value = data[elements[i].name];
|
||||
}
|
||||
@@ -87,9 +88,17 @@
|
||||
var data = {}
|
||||
var elements = [];
|
||||
elements = form.getElementsByTagName("input");
|
||||
for (var i = 0; i < elements.length; i++) data[elements[i].name] = elements[i].value;
|
||||
for (var i = 0; i < elements.length; i++) {
|
||||
if (elements[i].type == "hidden") continue;
|
||||
if (elements[i].type == "submit") continue;
|
||||
data[elements[i].name] = elements[i].value;
|
||||
}
|
||||
elements = form.getElementsByTagName("select");
|
||||
for (var i = 0; i < elements.length; i++) data[elements[i].name] = elements[i].value;
|
||||
for (var i = 0; i < elements.length; i++) {
|
||||
if (elements[i].type == "hidden") continue;
|
||||
if (elements[i].type == "submit") continue;
|
||||
data[elements[i].name] = elements[i].value;
|
||||
}
|
||||
localStorage.setItem("randomPlayQueue", JSON.stringify(data));
|
||||
}
|
||||
|
||||
@@ -122,6 +131,7 @@
|
||||
</h2>
|
||||
|
||||
<form id="randomPlayQueue" method="post" action="randomPlayQueue.view?">
|
||||
<sec:csrfInput />
|
||||
<table>
|
||||
<tr>
|
||||
<td><fmt:message key="more.random.text"/></td>
|
||||
@@ -291,6 +301,7 @@
|
||||
</h2>
|
||||
|
||||
<form method="post" enctype="multipart/form-data" action="upload.view">
|
||||
<sec:csrfInput />
|
||||
<table>
|
||||
<tr>
|
||||
<td><fmt:message key="more.upload.source"/></td>
|
||||
|
||||
@@ -241,6 +241,7 @@
|
||||
</form:form>
|
||||
|
||||
<form method="post" enctype="multipart/form-data" action="avatarUpload.view">
|
||||
<sec:csrfInput />
|
||||
<table>
|
||||
<tr>
|
||||
<td style="padding-right:1em"><fmt:message key="personalsettings.avatar.changecustom"/></td>
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
<body class="mainframe bgcolor1" onload="document.getElementById('usernameOrEmail').focus()">
|
||||
|
||||
<form action="recover.view" method="POST">
|
||||
<sec:csrfInput />
|
||||
<div class="bgcolor2 shadow" style="padding:20px 50px 20px 50px; margin-top:100px;margin-left:50px;margin-right:50px">
|
||||
|
||||
<div style="margin-left: auto; margin-right: auto; width: 45em">
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
</c:import>
|
||||
|
||||
<form method="post" action="shareSettings.view">
|
||||
<sec:csrfInput />
|
||||
|
||||
<table class="music indent">
|
||||
<tr>
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
</c:import>
|
||||
|
||||
<form method="post" action="sonosSettings.view">
|
||||
<sec:csrfInput />
|
||||
|
||||
<div>
|
||||
<input type="checkbox" name="sonosEnabled" id="sonosEnabled" class="checkbox"
|
||||
|
||||
@@ -125,6 +125,7 @@
|
||||
|
||||
<td style="padding-left:1em">
|
||||
<form method="post" action="search.view" target="main" name="searchForm">
|
||||
<sec:csrfInput />
|
||||
<td><input type="text" name="query" id="query" size="28" placeholder="${search}" onclick="select();"
|
||||
onkeyup="triggerInstantSearch();"></td>
|
||||
<td><a href="javascript:document.searchForm.submit()"><img src="<spring:theme code="searchImage"/>" alt="${search}" title="${search}"></a></td>
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
</c:import>
|
||||
|
||||
<form method="post" action="transcodingSettings.view">
|
||||
<sec:csrfInput />
|
||||
<table class="indent">
|
||||
<tr>
|
||||
<th><fmt:message key="transcodingsettings.name"/></th>
|
||||
|
||||
@@ -115,15 +115,15 @@ public class UserDaoTestCase extends DaoTestCaseBean2 {
|
||||
User user = new User("sindre", "secret", null);
|
||||
userDao.createUser(user);
|
||||
|
||||
User newUser = userDao.getUserByName("sindre");
|
||||
User newUser = userDao.getUserByName("sindre", true);
|
||||
assertNotNull("Error in getUserByName().", newUser);
|
||||
assertUserEquals(user, newUser);
|
||||
|
||||
assertNull("Error in getUserByName().", userDao.getUserByName("sindre2"));
|
||||
assertNull("Error in getUserByName().", userDao.getUserByName("sindre "));
|
||||
assertNull("Error in getUserByName().", userDao.getUserByName("bente"));
|
||||
assertNull("Error in getUserByName().", userDao.getUserByName(""));
|
||||
assertNull("Error in getUserByName().", userDao.getUserByName(null));
|
||||
assertNull("Error in getUserByName().", userDao.getUserByName("sindre2", true));
|
||||
assertNull("Error in getUserByName().", userDao.getUserByName("sindre ", true));
|
||||
assertNull("Error in getUserByName().", userDao.getUserByName("bente", true));
|
||||
assertNull("Error in getUserByName().", userDao.getUserByName("", true));
|
||||
assertNull("Error in getUserByName().", userDao.getUserByName(null, true));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user