001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.juneau.petstore.console.dev;
018
019import static java.nio.charset.StandardCharsets.*;
020
021import java.io.*;
022
023import org.apache.juneau.petstore.console.*;
024import org.apache.juneau.petstore.console.pages.*;
025import org.apache.juneau.rest.server.*;
026import org.apache.juneau.rest.server.view.*;
027import org.apache.juneau.rest.server.view.freemarker.*;
028
029/**
030 * Secure: an open console page demonstrating the bearer-token guarded {@link SecureApiRest}.
031 *
032 * <p>
033 * The page's "Try it" card calls {@code /console/dev/secure/api/whoami} from the browser with no token, the demo
034 * token or a wrong token, and shows the status and body inline.  The demo tokens come from
035 * {@code StubBearerTokenValidator}: {@code petstore-user} (alice) and {@code petstore-admin} (admin).
036 *
037 * <h5 class='section'>Example:</h5>
038 * <p class='bftl'>
039 *    &lt;@page tab="dev/secure" init=["/console/dev/secure/secure.js"]&gt;
040 *    &lt;@card id="try" title="Try it"&gt;
041 *    &lt;button type="button" data-secure-call="petstore-user"&gt;With the demo token&lt;/button&gt;
042 *    &lt;output id="secure-result"&gt;&lt;/output&gt;
043 *    &lt;/@card&gt;
044 *    &lt;/@page&gt;
045 * </p>
046 */
047@Rest(path="/secure", title="Secure", children={SecureApiRest.class})
048@SuppressWarnings({
049   "java:S110", // Inheritance depth comes from the BasicRestServlet hierarchy, not this page.
050   "resource" // The response writer is owned by the servlet container; Eclipse JDT @Owning warning is by design.
051})
052public class SecureRest extends PetstoreConsolePage {
053
054   private static final long serialVersionUID = 1L;
055
056   /**
057    * The Secure page.
058    *
059    * @param req The request; {@code ?builder} renders the builder twin.
060    * @return The page.
061    */
062   @RestGet(path="/")
063   public View page(RestRequest req) {
064      return builder(req) ? twin(req, DevPageBuilders.secure()) : FreemarkerView.of("secure.ftlh");
065   }
066
067   /**
068    * Serves the page-local script.
069    *
070    * @param res The response.
071    * @throws IOException If the bundled script can't be read.
072    */
073   @RestGet(path="/secure.js")
074   public void script(RestResponse res) throws IOException {
075      try (var in = SecureRest.class.getResourceAsStream("secure.js")) {
076         if (in == null)
077            throw new IllegalStateException("Missing classpath resource 'secure.js' beside " + SecureRest.class.getName());
078         res.setContentType("text/javascript;charset=utf-8");
079         res.getWriter().write(new String(in.readAllBytes(), UTF_8));
080      }
081   }
082}