From: Felix Date: Thu, 2 Jun 2016 07:16:11 +0000 (+0200) Subject: Merge "add: api for Test-memberid-lookup (addresses #4)" X-Git-Url: https://code.wpia.club/?p=gigi.git;a=commitdiff_plain;h=449f75a2b5d97ebf34bec2df715b71aa7e31afb0;hp=31bd86b7903b06266a84b3350914858c8a207b35 Merge "add: api for Test-memberid-lookup (addresses #4)" --- diff --git a/src/org/cacert/gigi/output/template/ForeachStatement.java b/src/org/cacert/gigi/output/template/ForeachStatement.java index 8c12122b..4c8b1027 100644 --- a/src/org/cacert/gigi/output/template/ForeachStatement.java +++ b/src/org/cacert/gigi/output/template/ForeachStatement.java @@ -7,12 +7,24 @@ import java.util.Map; import org.cacert.gigi.localisation.Language; +/** + * Outputs an {@link Outputable} multiple times based on a given + * {@link IterableDataset}. + */ public final class ForeachStatement implements Translatable { private final String variable; private final TemplateBlock body; + /** + * Creates a new {@link ForeachStatement}. + * + * @param variable + * the variable to take the {@link IterableDataset} from. + * @param body + * the body to output multiple times. + */ public ForeachStatement(String variable, TemplateBlock body) { this.variable = variable; this.body = body; diff --git a/src/org/cacert/gigi/output/template/Form.java b/src/org/cacert/gigi/output/template/Form.java index ed1a8668..366d31c5 100644 --- a/src/org/cacert/gigi/output/template/Form.java +++ b/src/org/cacert/gigi/output/template/Form.java @@ -13,6 +13,9 @@ import org.cacert.gigi.localisation.Language; import org.cacert.gigi.pages.Page; import org.cacert.gigi.util.RandomToken; +/** + * A generic HTML-form that handles CSRF-token creation. + */ public abstract class Form implements Outputable { public static final String CSRF_FIELD = "csrf"; @@ -21,10 +24,24 @@ public abstract class Form implements Outputable { private final String action; + /** + * Creates a new {@link Form}. + * + * @param hsr + * the request to register the form against. + */ public Form(HttpServletRequest hsr) { this(hsr, null); } + /** + * Creates a new {@link Form}. + * + * @param hsr + * the request to register the form against. + * @param action + * the target path where the form should be submitted + */ public Form(HttpServletRequest hsr, String action) { csrf = RandomToken.generateToken(32); this.action = action; @@ -32,6 +49,17 @@ public abstract class Form implements Outputable { hs.setAttribute("form/" + getClass().getName() + "/" + csrf, this); } + /** + * Update the forms internal state based on submitted data. + * + * @param out + * the stream to the user. + * @param req + * the request to take the initial data from + * @return true, iff the form succeeded an the user should be redirected. + * @throws GigiApiException + * if internal operations went wrong. + */ public abstract boolean submit(PrintWriter out, HttpServletRequest req) throws GigiApiException; protected String getCsrfFieldName() { @@ -52,9 +80,19 @@ public abstract class Form implements Outputable { out.println("'>"); } + /** + * Outputs the forms contents. + * + * @param out + * Stream to the user + * @param l + * {@link Language} to translate text to + * @param vars + * Variables supplied from the outside. + */ protected abstract void outputContent(PrintWriter out, Language l, Map vars); - boolean failed; + private boolean failed; protected void outputError(PrintWriter out, ServletRequest req, String text, Object... contents) { if ( !failed) { @@ -91,6 +129,17 @@ public abstract class Form implements Outputable { return csrf; } + /** + * Re-fetches a form e.g. when a Post-request is received. + * + * @param req + * the request that is directed to the form. + * @param target + * the {@link Class} of the expected form + * @return the form where this request is directed to. + * @throws CSRFException + * if no CSRF-token is found or the token is wrong. + */ public static T getForm(HttpServletRequest req, Class target) throws CSRFException { String csrf = req.getParameter(CSRF_FIELD); if (csrf == null) { diff --git a/src/org/cacert/gigi/output/template/IfStatement.java b/src/org/cacert/gigi/output/template/IfStatement.java index 29cfc768..f2248bcc 100644 --- a/src/org/cacert/gigi/output/template/IfStatement.java +++ b/src/org/cacert/gigi/output/template/IfStatement.java @@ -6,6 +6,10 @@ import java.util.Map; import org.cacert.gigi.localisation.Language; +/** + * One ore two {@link Outputable}s that are emitted conditionally if a given + * variable is neither null nor {@link Boolean#FALSE}. + */ public final class IfStatement implements Translatable { private final String variable; @@ -14,12 +18,30 @@ public final class IfStatement implements Translatable { private final TemplateBlock iffalse; + /** + * Creates a new {@link IfStatement} with an empty else-part. + * + * @param variable + * the variable to check + * @param body + * the body to emit conditionally. + */ public IfStatement(String variable, TemplateBlock body) { this.variable = variable; this.iftrue = body; this.iffalse = null; } + /** + * Creates a new {@link IfStatement} with an else-block. + * + * @param variable + * the variable to check + * @param iftrue + * the block to emit if the check succeeds. + * @param iffalse + * the block to emit if the check fails + */ public IfStatement(String variable, TemplateBlock iftrue, TemplateBlock iffalse) { this.variable = variable; this.iftrue = iftrue; diff --git a/src/org/cacert/gigi/output/template/IterableDataset.java b/src/org/cacert/gigi/output/template/IterableDataset.java index e95dce8f..8c96727b 100644 --- a/src/org/cacert/gigi/output/template/IterableDataset.java +++ b/src/org/cacert/gigi/output/template/IterableDataset.java @@ -5,7 +5,8 @@ import java.util.Map; import org.cacert.gigi.localisation.Language; /** - * Represents some kind of data, that may be iterated over in a template. + * Represents some kind of data, that may be iterated over in a template using + * the foreach statement. */ public interface IterableDataset { diff --git a/src/org/cacert/gigi/output/template/OutputVariableCommand.java b/src/org/cacert/gigi/output/template/OutputVariableCommand.java index 908a0377..5dce3aed 100644 --- a/src/org/cacert/gigi/output/template/OutputVariableCommand.java +++ b/src/org/cacert/gigi/output/template/OutputVariableCommand.java @@ -6,12 +6,22 @@ import java.util.Map; import org.cacert.gigi.localisation.Language; +/** + * Emits a variable. + */ public final class OutputVariableCommand implements Translatable { private final String raw; private final boolean unescaped; + /** + * Creates a new OutputVariableCommand. + * + * @param raw + * the variable to emit. If starting with ! the + * variable is emitted non-HTML-escaped. + */ public OutputVariableCommand(String raw) { if (raw.charAt(0) == '!') { unescaped = true; diff --git a/src/org/cacert/gigi/output/template/Outputable.java b/src/org/cacert/gigi/output/template/Outputable.java index 5716162a..02fea411 100644 --- a/src/org/cacert/gigi/output/template/Outputable.java +++ b/src/org/cacert/gigi/output/template/Outputable.java @@ -5,7 +5,20 @@ import java.util.Map; import org.cacert.gigi.localisation.Language; +/** + * An object that is outputable to the user normally in an HTML-page. + */ public interface Outputable { + /** + * Writes this object's content to the given output stream. + * + * @param out + * the PrintWriter to the user. + * @param l + * the {@link Language} to translate localizable strings to. + * @param vars + * a map of variable assignments for this template. + */ public void output(PrintWriter out, Language l, Map vars); } diff --git a/src/org/cacert/gigi/output/template/OutputableArrayIterable.java b/src/org/cacert/gigi/output/template/OutputableArrayIterable.java index 5a78e73b..49895407 100644 --- a/src/org/cacert/gigi/output/template/OutputableArrayIterable.java +++ b/src/org/cacert/gigi/output/template/OutputableArrayIterable.java @@ -4,14 +4,26 @@ import java.util.Map; import org.cacert.gigi.localisation.Language; +/** + * Generic implementation of {@link IterableDataset} that is fed by an array. + */ public class OutputableArrayIterable implements IterableDataset { - Object[] content; + private Object[] content; - String targetName; + private String targetName; - int index = 0; + private int index = 0; + /** + * Creates a new {@link OutputableArrayIterable}. + * + * @param content + * the objects to be iterated over. + * @param targetName + * the variable where the contents of the array to be put in the + * loop. + */ public OutputableArrayIterable(Object[] content, String targetName) { this.content = content; this.targetName = targetName; diff --git a/src/org/cacert/gigi/output/template/Scope.java b/src/org/cacert/gigi/output/template/Scope.java index 9a15b3a4..38e25ebc 100644 --- a/src/org/cacert/gigi/output/template/Scope.java +++ b/src/org/cacert/gigi/output/template/Scope.java @@ -6,12 +6,24 @@ import java.util.Map; import org.cacert.gigi.localisation.Language; +/** + * Builds a variable scope around another {@link Outputable}, statically filling + * variables. + */ public class Scope implements Outputable { private Map vars; private Outputable out; + /** + * Creates a new {@link Scope}. + * + * @param out + * the enclosed {@link Outputable} + * @param vars + * the variables to assign in the inner scope. + */ public Scope(Outputable out, Map vars) { this.out = out; this.vars = vars; diff --git a/src/org/cacert/gigi/output/template/SprintfCommand.java b/src/org/cacert/gigi/output/template/SprintfCommand.java index 385da25c..cbd79e57 100644 --- a/src/org/cacert/gigi/output/template/SprintfCommand.java +++ b/src/org/cacert/gigi/output/template/SprintfCommand.java @@ -13,12 +13,24 @@ import java.util.regex.Pattern; import org.cacert.gigi.localisation.Language; import org.cacert.gigi.util.HTMLEncoder; +/** + * A pattern that is to be translated before variables are inserted. + */ public final class SprintfCommand implements Translatable { private final String text; private final String[] store; + /** + * Creates a new SprintfCommand based on its pre-parsed contents + * + * @param text + * a string with {0},{1},.. as placeholders. + * @param store + * the data to put into the placeholders: ${var}, $!{var}, + * !'plain'. + */ public SprintfCommand(String text, List store) { this.text = text; this.store = store.toArray(new String[store.size()]); @@ -28,7 +40,13 @@ public final class SprintfCommand implements Translatable { private static final Pattern processingInstruction = Pattern.compile("(" + VARIABLE + ")|(!'[^{}'\\$]*)'"); - public SprintfCommand(String content) { + /** + * Creates a new SprintfCommand that is parsed as from template source. + * + * @param content + * the part from the template that is to be parsed + */ + protected SprintfCommand(String content) { StringBuffer raw = new StringBuffer(); List var = new LinkedList(); int counter = 0; @@ -82,6 +100,17 @@ public final class SprintfCommand implements Translatable { s.add(text); } + /** + * Creates a simple {@link SprintfCommand} wrapped in a {@link Scope} to fit + * in now constant variables into this template. + * + * @param msg + * the message (to be translated) with {0},{1},... + * as placeholders. + * @param vars + * the variables to put into the placeholders. + * @return the constructed {@link Outputable} + */ public static Outputable createSimple(String msg, String... vars) { HashMap scope = new HashMap<>(); String[] store = new String[vars.length]; diff --git a/src/org/cacert/gigi/output/template/Template.java b/src/org/cacert/gigi/output/template/Template.java index 17051595..cc56baf8 100644 --- a/src/org/cacert/gigi/output/template/Template.java +++ b/src/org/cacert/gigi/output/template/Template.java @@ -22,6 +22,9 @@ import org.cacert.gigi.output.DateSelector; import org.cacert.gigi.util.DayDate; import org.cacert.gigi.util.HTMLEncoder; +/** + * Represents a loaded template file. + */ public class Template implements Outputable { private static class ParseResult { @@ -63,6 +66,14 @@ public class Template implements Outputable { private static final Pattern ELSE_PATTERN = Pattern.compile(" ?\\} ?else ?\\{ ?"); + /** + * Creates a new template by parsing the contents from the given URL. This + * constructor will fail on syntax error. When the URL points to a file, + * {@link File#lastModified()} is monitored for changes of the template. + * + * @param u + * the URL to load the template from. UTF-8 is chosen as charset. + */ public Template(URL u) { try { Reader r = new InputStreamReader(u.openStream(), "UTF-8"); @@ -81,6 +92,13 @@ public class Template implements Outputable { } } + /** + * Creates a new template by parsing the contents from the given reader. + * This constructor will fail on syntax error. + * + * @param r + * the Reader containing the data. + */ public Template(Reader r) { try { data = parse(r).getBlock(null); diff --git a/src/org/cacert/gigi/output/template/Translatable.java b/src/org/cacert/gigi/output/template/Translatable.java index b15ffb93..4df11474 100644 --- a/src/org/cacert/gigi/output/template/Translatable.java +++ b/src/org/cacert/gigi/output/template/Translatable.java @@ -2,7 +2,17 @@ package org.cacert.gigi.output.template; import java.util.Collection; +/** + * An {@link Outputable} that wants to give static strings to translation + * collection. + */ public interface Translatable extends Outputable { + /** + * Adds all static translation Strings to the given {@link Collection}. + * + * @param s + * the {@link Collection} to add the Strings to. + */ public void addTranslations(Collection s); } diff --git a/src/org/cacert/gigi/output/template/TranslateCommand.java b/src/org/cacert/gigi/output/template/TranslateCommand.java index 9da43524..d291e9d4 100644 --- a/src/org/cacert/gigi/output/template/TranslateCommand.java +++ b/src/org/cacert/gigi/output/template/TranslateCommand.java @@ -7,10 +7,19 @@ import java.util.Map; import org.cacert.gigi.localisation.Language; import org.cacert.gigi.util.HTMLEncoder; +/** + * Wraps a String that needs to be translated before it is printed to the user. + */ public final class TranslateCommand implements Translatable { private final String raw; + /** + * Creates a new TranslateCommand that wraps the given String. + * + * @param raw + * the String to be translated. + */ public TranslateCommand(String raw) { this.raw = raw; } @@ -20,6 +29,11 @@ public final class TranslateCommand implements Translatable { out.print(HTMLEncoder.encodeHTML(l.getTranslation(raw))); } + /** + * Gets the raw, untranslated String. + * + * @return the raw, untranslated String. + */ public String getRaw() { return raw; } diff --git a/src/org/cacert/gigi/pages/Verify.java b/src/org/cacert/gigi/pages/Verify.java index 0c848542..0f88fe40 100644 --- a/src/org/cacert/gigi/pages/Verify.java +++ b/src/org/cacert/gigi/pages/Verify.java @@ -2,6 +2,7 @@ package org.cacert.gigi.pages; import java.io.IOException; import java.io.PrintWriter; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; @@ -18,9 +19,9 @@ import org.cacert.gigi.output.template.SprintfCommand; public class Verify extends Page { - private static final SprintfCommand emailAddressVerified = new SprintfCommand("Email address ${subject} verified"); + private static final SprintfCommand emailAddressVerified = new SprintfCommand("Email address {0} verified", Arrays.asList("${subject}")); - private static final SprintfCommand domainVerified = new SprintfCommand("Domain ${subject} verified"); + private static final SprintfCommand domainVerified = new SprintfCommand("Domain {0} verified", Arrays.asList("${subject}")); private class VerificationForm extends Form { diff --git a/src/org/cacert/gigi/util/AuthorizationContext.java b/src/org/cacert/gigi/util/AuthorizationContext.java index 114475c5..6e4bd8bf 100644 --- a/src/org/cacert/gigi/util/AuthorizationContext.java +++ b/src/org/cacert/gigi/util/AuthorizationContext.java @@ -73,7 +73,8 @@ public class AuthorizationContext implements Outputable { } out.println(l.getTranslation("with")); - out.println(vars.get("loginMethod")); + ((Outputable) vars.get("loginMethod")).output(out, l, vars); + out.println(); out.println(""); if (supporterTicketId != null) { out.println("
"); diff --git a/tests/org/cacert/gigi/LoginTest.java b/tests/org/cacert/gigi/LoginTest.java index 29456c7b..cb575caf 100644 --- a/tests/org/cacert/gigi/LoginTest.java +++ b/tests/org/cacert/gigi/LoginTest.java @@ -1,9 +1,12 @@ package org.cacert.gigi; +import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; import java.io.IOException; +import java.net.URLConnection; +import org.cacert.gigi.testUtils.IOUtils; import org.cacert.gigi.testUtils.ManagedTest; import org.junit.Test; @@ -45,4 +48,14 @@ public class LoginTest extends ManagedTest { get(cookie, "/logout").getHeaderField("Location"); } + @Test + public void testLoginMethodDisplay() throws IOException { + String email = createUniqueName() + "@testmail.org"; + createVerifiedUser("an", "bn", email, TEST_PASSWORD); + String l = login(email, TEST_PASSWORD); + URLConnection c = get(l, ""); + String readURL = IOUtils.readURL(c); + assertThat(readURL, containsString("Password")); + } + }