fix menu error
This commit is contained in:
parent
80904209b3
commit
2dc32fb8c9
5 changed files with 571 additions and 200 deletions
|
@ -9,7 +9,7 @@
|
||||||
</li>
|
</li>
|
||||||
<li data-ng-show="access.viewUsers" data-ng-class="(path[2] == 'users' || path[1] == 'user') && 'active'"><a href="#/realms/{{realm.realm}}/users">Users</a>
|
<li data-ng-show="access.viewUsers" data-ng-class="(path[2] == 'users' || path[1] == 'user') && 'active'"><a href="#/realms/{{realm.realm}}/users">Users</a>
|
||||||
</li>
|
</li>
|
||||||
<li data-ng-show="access.viewRealm" data-ng-class="(path[2] == 'roles' || (path[1] == 'role' & path[3] != 'applications') && 'active'"><a href="#/realms/{{realm.realm}}/roles">Roles</a>
|
<li data-ng-show="access.viewRealm" data-ng-class="(path[2] == 'roles' || (path[1] == 'role' && path[3] != 'applications')) && 'active'"><a href="#/realms/{{realm.realm}}/roles">Roles</a>
|
||||||
</li>
|
</li>
|
||||||
<li data-ng-show="access.viewApplications" data-ng-class="(path[2] == 'applications' || path[1] == 'application' || path[3] == 'applications') && 'active'"><a href="#/realms/{{realm.realm}}/applications">Applications</a></li>
|
<li data-ng-show="access.viewApplications" data-ng-class="(path[2] == 'applications' || path[1] == 'application' || path[3] == 'applications') && 'active'"><a href="#/realms/{{realm.realm}}/applications">Applications</a></li>
|
||||||
<li data-ng-show="access.viewClients" data-ng-class="(path[2] == 'oauth-clients' || path[1] == 'oauth-client') && 'active'"><a href="#/realms/{{realm.realm}}/oauth-clients">OAuth Clients</a></li>
|
<li data-ng-show="access.viewClients" data-ng-class="(path[2] == 'oauth-clients' || path[1] == 'oauth-client') && 'active'"><a href="#/realms/{{realm.realm}}/oauth-clients">OAuth Clients</a></li>
|
||||||
|
|
|
@ -1,9 +1,15 @@
|
||||||
package org.keycloak.services.util;
|
package org.keycloak.services.util;
|
||||||
|
|
||||||
|
import org.jboss.resteasy.spi.HttpResponse;
|
||||||
import org.jboss.resteasy.spi.ResteasyProviderFactory;
|
import org.jboss.resteasy.spi.ResteasyProviderFactory;
|
||||||
|
|
||||||
import javax.servlet.http.Cookie;
|
import javax.servlet.http.Cookie;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import javax.ws.rs.core.HttpHeaders;
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
@ -23,6 +29,14 @@ public class CookieHelper {
|
||||||
* @param secure
|
* @param secure
|
||||||
* @param httpOnly
|
* @param httpOnly
|
||||||
*/
|
*/
|
||||||
|
public static void addCookie2(String name, String value, String path, String domain, String comment, int maxAge, boolean secure, boolean httpOnly) {
|
||||||
|
HttpResponse response = ResteasyProviderFactory.getContextData(HttpResponse.class);
|
||||||
|
StringBuffer cookieBuf = new StringBuffer();
|
||||||
|
ServerCookie.appendCookieValue(cookieBuf, 1, name, value, path, domain, comment, maxAge, secure, httpOnly);
|
||||||
|
String cookie = cookieBuf.toString();
|
||||||
|
response.getOutputHeaders().add(HttpHeaders.SET_COOKIE, cookie);
|
||||||
|
}
|
||||||
|
|
||||||
public static void addCookie(String name, String value, String path, String domain, String comment, int maxAge, boolean secure, boolean httpOnly) {
|
public static void addCookie(String name, String value, String path, String domain, String comment, int maxAge, boolean secure, boolean httpOnly) {
|
||||||
HttpServletResponse response = ResteasyProviderFactory.getContextData(HttpServletResponse.class);
|
HttpServletResponse response = ResteasyProviderFactory.getContextData(HttpServletResponse.class);
|
||||||
Cookie cookie = new Cookie(name, value);
|
Cookie cookie = new Cookie(name, value);
|
||||||
|
@ -36,4 +50,6 @@ public class CookieHelper {
|
||||||
response.addCookie(cookie);
|
response.addCookie(cookie);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
347
services/src/main/java/org/keycloak/services/util/ServerCookie.java
Executable file
347
services/src/main/java/org/keycloak/services/util/ServerCookie.java
Executable file
|
@ -0,0 +1,347 @@
|
||||||
|
package org.keycloak.services.util;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.text.FieldPosition;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Server-side cookie representation. borrowed from Tomcat.
|
||||||
|
*/
|
||||||
|
public class ServerCookie implements Serializable
|
||||||
|
{
|
||||||
|
private static final String tspecials = ",; ";
|
||||||
|
private static final String tspecials2 = "()<>@,;:\\\"/[]?={} \t";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tests a string and returns true if the string counts as a
|
||||||
|
* reserved token in the Java language.
|
||||||
|
*
|
||||||
|
* @param value the <code>String</code> to be tested
|
||||||
|
*
|
||||||
|
* @return <code>true</code> if the <code>String</code> is a reserved
|
||||||
|
* token; <code>false</code> if it is not
|
||||||
|
*/
|
||||||
|
public static boolean isToken(String value)
|
||||||
|
{
|
||||||
|
if (value == null) return true;
|
||||||
|
int len = value.length();
|
||||||
|
|
||||||
|
for (int i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
char c = value.charAt(i);
|
||||||
|
|
||||||
|
if (tspecials.indexOf(c) != -1)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean containsCTL(String value, int version)
|
||||||
|
{
|
||||||
|
if (value == null) return false;
|
||||||
|
int len = value.length();
|
||||||
|
for (int i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
char c = value.charAt(i);
|
||||||
|
if (c < 0x20 || c >= 0x7f)
|
||||||
|
{
|
||||||
|
if (c == 0x09)
|
||||||
|
continue; //allow horizontal tabs
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static boolean isToken2(String value)
|
||||||
|
{
|
||||||
|
if (value == null) return true;
|
||||||
|
int len = value.length();
|
||||||
|
|
||||||
|
for (int i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
char c = value.charAt(i);
|
||||||
|
if (tspecials2.indexOf(c) != -1)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated - Not used
|
||||||
|
*/
|
||||||
|
public static boolean checkName(String name)
|
||||||
|
{
|
||||||
|
if (!isToken(name)
|
||||||
|
|| name.equalsIgnoreCase("Comment") // rfc2019
|
||||||
|
|| name.equalsIgnoreCase("Discard") // rfc2965
|
||||||
|
|| name.equalsIgnoreCase("Domain") // rfc2019
|
||||||
|
|| name.equalsIgnoreCase("Expires") // Netscape
|
||||||
|
|| name.equalsIgnoreCase("Max-Age") // rfc2019
|
||||||
|
|| name.equalsIgnoreCase("Path") // rfc2019
|
||||||
|
|| name.equalsIgnoreCase("Secure") // rfc2019
|
||||||
|
|| name.equalsIgnoreCase("Version") // rfc2019
|
||||||
|
// TODO remaining RFC2965 attributes
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------- Cookie parsing tools
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the header name to set the cookie, based on cookie version.
|
||||||
|
*/
|
||||||
|
public static String getCookieHeaderName(int version)
|
||||||
|
{
|
||||||
|
// TODO Re-enable logging when RFC2965 is implemented
|
||||||
|
// log( (version==1) ? "Set-Cookie2" : "Set-Cookie");
|
||||||
|
if (version == 1)
|
||||||
|
{
|
||||||
|
// XXX RFC2965 not referenced in Servlet Spec
|
||||||
|
// Set-Cookie2 is not supported by Netscape 4, 6, IE 3, 5
|
||||||
|
// Set-Cookie2 is supported by Lynx and Opera
|
||||||
|
// Need to check on later IE and FF releases but for now...
|
||||||
|
// RFC2109
|
||||||
|
return "Set-Cookie";
|
||||||
|
// return "Set-Cookie2";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Old Netscape
|
||||||
|
return "Set-Cookie";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* US locale - all HTTP dates are in english
|
||||||
|
*/
|
||||||
|
private final static Locale LOCALE_US = Locale.US;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GMT timezone - all HTTP dates are on GMT
|
||||||
|
*/
|
||||||
|
public final static TimeZone GMT_ZONE = TimeZone.getTimeZone("GMT");
|
||||||
|
/**
|
||||||
|
* Pattern used for old cookies
|
||||||
|
*/
|
||||||
|
private final static String OLD_COOKIE_PATTERN = "EEE, dd-MMM-yyyy HH:mm:ss z";
|
||||||
|
|
||||||
|
|
||||||
|
private final static DateFormat oldCookieFormat = new SimpleDateFormat(OLD_COOKIE_PATTERN, LOCALE_US);
|
||||||
|
|
||||||
|
public static String formatOldCookie(Date d)
|
||||||
|
{
|
||||||
|
String ocf = null;
|
||||||
|
synchronized (oldCookieFormat)
|
||||||
|
{
|
||||||
|
ocf = oldCookieFormat.format(d);
|
||||||
|
}
|
||||||
|
return ocf;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void formatOldCookie(Date d, StringBuffer sb,
|
||||||
|
FieldPosition fp)
|
||||||
|
{
|
||||||
|
synchronized (oldCookieFormat)
|
||||||
|
{
|
||||||
|
oldCookieFormat.format(d, sb, fp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static final String ancientDate = formatOldCookie(new Date(10000));
|
||||||
|
|
||||||
|
|
||||||
|
// TODO RFC2965 fields also need to be passed
|
||||||
|
public static void appendCookieValue(StringBuffer headerBuf,
|
||||||
|
int version,
|
||||||
|
String name,
|
||||||
|
String value,
|
||||||
|
String path,
|
||||||
|
String domain,
|
||||||
|
String comment,
|
||||||
|
int maxAge,
|
||||||
|
boolean isSecure,
|
||||||
|
boolean httpOnly)
|
||||||
|
{
|
||||||
|
StringBuffer buf = new StringBuffer();
|
||||||
|
// Servlet implementation checks name
|
||||||
|
buf.append(name);
|
||||||
|
buf.append("=");
|
||||||
|
// Servlet implementation does not check anything else
|
||||||
|
|
||||||
|
maybeQuote2(version, buf, value);
|
||||||
|
|
||||||
|
// Add version 1 specific information
|
||||||
|
if (version == 1)
|
||||||
|
{
|
||||||
|
// Version=1 ... required
|
||||||
|
buf.append("; Version=1");
|
||||||
|
|
||||||
|
// Comment=comment
|
||||||
|
if (comment != null)
|
||||||
|
{
|
||||||
|
buf.append("; Comment=");
|
||||||
|
maybeQuote2(version, buf, comment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add domain information, if present
|
||||||
|
if (domain != null)
|
||||||
|
{
|
||||||
|
buf.append("; Domain=");
|
||||||
|
maybeQuote2(version, buf, domain);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Max-Age=secs ... or use old "Expires" format
|
||||||
|
// TODO RFC2965 Discard
|
||||||
|
if (maxAge >= 0)
|
||||||
|
{
|
||||||
|
// Wdy, DD-Mon-YY HH:MM:SS GMT ( Expires Netscape format )
|
||||||
|
buf.append("; Expires=");
|
||||||
|
// To expire immediately we need to set the time in past
|
||||||
|
if (maxAge == 0)
|
||||||
|
buf.append(ancientDate);
|
||||||
|
else
|
||||||
|
formatOldCookie
|
||||||
|
(new Date(System.currentTimeMillis() +
|
||||||
|
maxAge * 1000L), buf,
|
||||||
|
new FieldPosition(0));
|
||||||
|
|
||||||
|
buf.append("; Max-Age=");
|
||||||
|
buf.append(maxAge);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Path=path
|
||||||
|
if (path != null)
|
||||||
|
{
|
||||||
|
buf.append("; Path=");
|
||||||
|
buf.append(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Secure
|
||||||
|
if (isSecure)
|
||||||
|
{
|
||||||
|
buf.append("; Secure");
|
||||||
|
}
|
||||||
|
|
||||||
|
// HttpOnly
|
||||||
|
if (httpOnly)
|
||||||
|
{
|
||||||
|
buf.append("; HttpOnly");
|
||||||
|
}
|
||||||
|
|
||||||
|
headerBuf.append(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated - Not used
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public static void maybeQuote(int version, StringBuffer buf, String value)
|
||||||
|
{
|
||||||
|
// special case - a \n or \r shouldn't happen in any case
|
||||||
|
if (isToken(value))
|
||||||
|
{
|
||||||
|
buf.append(value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
buf.append('"');
|
||||||
|
buf.append(escapeDoubleQuotes(value, 0, value.length()));
|
||||||
|
buf.append('"');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean alreadyQuoted(String value)
|
||||||
|
{
|
||||||
|
if (value == null || value.length() == 0) return false;
|
||||||
|
return (value.charAt(0) == '\"' && value.charAt(value.length() - 1) == '\"');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Quotes values using rules that vary depending on Cookie version.
|
||||||
|
*
|
||||||
|
* @param version
|
||||||
|
* @param buf
|
||||||
|
* @param value
|
||||||
|
*/
|
||||||
|
public static void maybeQuote2(int version, StringBuffer buf, String value)
|
||||||
|
{
|
||||||
|
if (value == null || value.length() == 0)
|
||||||
|
{
|
||||||
|
buf.append("\"\"");
|
||||||
|
}
|
||||||
|
else if (containsCTL(value, version))
|
||||||
|
throw new IllegalArgumentException("Control character in cookie value, consider BASE64 encoding your value");
|
||||||
|
else if (alreadyQuoted(value))
|
||||||
|
{
|
||||||
|
buf.append('"');
|
||||||
|
buf.append(escapeDoubleQuotes(value, 1, value.length() - 1));
|
||||||
|
buf.append('"');
|
||||||
|
}
|
||||||
|
else if (version == 0 && !isToken(value))
|
||||||
|
{
|
||||||
|
buf.append('"');
|
||||||
|
buf.append(escapeDoubleQuotes(value, 0, value.length()));
|
||||||
|
buf.append('"');
|
||||||
|
}
|
||||||
|
else if (version == 1 && !isToken2(value))
|
||||||
|
{
|
||||||
|
buf.append('"');
|
||||||
|
buf.append(escapeDoubleQuotes(value, 0, value.length()));
|
||||||
|
buf.append('"');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
buf.append(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Escapes any double quotes in the given string.
|
||||||
|
*
|
||||||
|
* @param s the input string
|
||||||
|
* @param beginIndex start index inclusive
|
||||||
|
* @param endIndex exclusive
|
||||||
|
* @return The (possibly) escaped string
|
||||||
|
*/
|
||||||
|
private static String escapeDoubleQuotes(String s, int beginIndex, int endIndex)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (s == null || s.length() == 0 || s.indexOf('"') == -1)
|
||||||
|
{
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuffer b = new StringBuffer();
|
||||||
|
for (int i = beginIndex; i < endIndex; i++)
|
||||||
|
{
|
||||||
|
char c = s.charAt(i);
|
||||||
|
if (c == '\\')
|
||||||
|
{
|
||||||
|
b.append(c);
|
||||||
|
//ignore the character after an escape, just append it
|
||||||
|
if (++i >= endIndex) throw new IllegalArgumentException("Invalid escape character in cookie value.");
|
||||||
|
b.append(s.charAt(i));
|
||||||
|
}
|
||||||
|
else if (c == '"')
|
||||||
|
b.append('\\').append('"');
|
||||||
|
else
|
||||||
|
b.append(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
return b.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -3,6 +3,7 @@ package org.keycloak.testsuite.forms;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.ClassRule;
|
import org.junit.ClassRule;
|
||||||
import org.junit.FixMethodOrder;
|
import org.junit.FixMethodOrder;
|
||||||
|
import org.junit.Ignore;
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.rules.RuleChain;
|
import org.junit.rules.RuleChain;
|
||||||
|
@ -102,6 +103,13 @@ public class FederationProvidersIntegrationTest {
|
||||||
@WebResource
|
@WebResource
|
||||||
protected AccountPasswordPage changePasswordPage;
|
protected AccountPasswordPage changePasswordPage;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Ignore
|
||||||
|
public void runit() throws Exception {
|
||||||
|
Thread.sleep(10000000);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static UserModel addUser(KeycloakSession session, RealmModel realm, String username, String email, String password) {
|
static UserModel addUser(KeycloakSession session, RealmModel realm, String username, String email, String password) {
|
||||||
UserModel user = session.users().addUser(realm, username);
|
UserModel user = session.users().addUser(realm, username);
|
||||||
user.setEmail(email);
|
user.setEmail(email);
|
||||||
|
|
Loading…
Reference in a new issue