class OTPKtrl extends BaseKontroller {

    private static final Logger log = LoggerFactory.getLogger(OTPKtrl.class);

    public static final boolean requireOTP = "required".equals(AppConfig.getProperty("oneTimePassword"));

    //QR image size
    private static final int QR_IMAGE_WIDTH = 325;
    private static final int QR_IMAGE_HEIGHT = 325;

    @Model(name = "qrImage")
    String qrImage;
    @Model(name = "sharedSecret")
    String sharedSecret;

    public OTPKtrl(HttpServletRequest request, HttpServletResponse response) {
        super(request, response);
    }

    @Kontrol(path = "/admin/viewOTP", method = MethodType.GET)
    public String viewOTP() throws ServletException {

        sharedSecret = OTPUtil.generateSecret();

        try {
            AuthUtil.setOTPSecret(getRequest().getSession(), sharedSecret);
        } catch (GeneralSecurityException ex) {
            log.error(ex.toString(), ex);
            throw new ServletException(ex.toString(), ex);
        }

        qrImage = new Date().getTime() + ".png";

        return "/admin/two-factor_otp.html";
    }

    @Kontrol(path = "/admin/otpSubmit", method = MethodType.POST)
    public String otpSubmit() throws ServletException {

        try {
            AuthDB.updateSharedSecret(sharedSecret, AuthUtil.getAuthToken(getRequest().getSession()));
        } catch (SQLException | GeneralSecurityException ex) {
            log.error(ex.toString(), ex);
            throw new ServletException(ex.toString(), ex);
        }

        if (requireOTP) {
            AuthUtil.deleteAllSession(getRequest().getSession());
        }
        return "redirect:/logout.ktrl";

    }


    @Kontrol(path = "/admin/qrImage", method = MethodType.GET)
    public String qrImage() throws ServletException {<FILL_FUNCTION_BODY>}
}


        String username;
        String secret;
        try {
            username = UserDB.getUser(AuthUtil.getUserId(getRequest().getSession())).getUsername();
            secret = AuthUtil.getOTPSecret(getRequest().getSession());
            AuthUtil.setOTPSecret(getRequest().getSession(), null);
        } catch (SQLException | GeneralSecurityException ex) {
            log.error(ex.toString(), ex);
            throw new ServletException(ex.toString(), ex);
        }

        try {

            String qrCodeText = "otpauth://totp/Bastillion%20%28" + URLEncoder.encode(getRequest().getHeader("host").replaceAll("\\:.*$", ""), "utf-8") + "%29:" + username + "?secret=" + secret;

            QRCodeWriter qrWriter = new QRCodeWriter();

            Hashtable<EncodeHintType, String> hints = new Hashtable<>();
            hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");


            BitMatrix matrix = qrWriter.encode(qrCodeText, BarcodeFormat.QR_CODE, QR_IMAGE_WIDTH, QR_IMAGE_HEIGHT, hints);
            getResponse().setContentType("image/png");

            BufferedImage image = new BufferedImage(QR_IMAGE_WIDTH, QR_IMAGE_HEIGHT, BufferedImage.TYPE_INT_RGB);

            Graphics2D graphics = (Graphics2D) image.getGraphics();
            graphics.setColor(Color.WHITE);
            graphics.fillRect(0, 0, QR_IMAGE_WIDTH, QR_IMAGE_HEIGHT);
            graphics.setColor(Color.BLACK);

            for (int x = 0; x < QR_IMAGE_WIDTH; x++) {
                for (int y = 0; y < QR_IMAGE_HEIGHT; y++) {
                    if (matrix.get(x, y)) {
                        graphics.fillRect(x, y, 1, 1);
                    }
                }
            }
            ImageIO.write(image, "png", getResponse().getOutputStream());

            getResponse().getOutputStream().flush();
            getResponse().getOutputStream().close();

        } catch (IOException | WriterException ex) {
            log.error(ex.toString(), ex);
            throw new ServletException(ex.toString(), ex);
        }

        return null;

    
<no_super_class>