- some bugfixes in pom, sql, ..
- set explicit order in sql execute
- add examples: action password change, login to check for anonymous user login
- update README.txt
git-svn-id: https://svn.apache.org/repos/asf/turbine/maven/archetypes/trunk/turbine-webapp-4.0@1769768 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 709b16a..791f6f5 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -29,7 +29,7 @@
JNDI Jetty Update
</action>
<action dev="tv" type="add">
- add testing in place with "integration-test"
+ Add testing in place with "integration-test"
</action>
<action dev="tv" type="update">
Turbine annotations, use auto detect Torque adapter
diff --git a/src/main/resources/archetype-resources/docs/README.txt b/src/main/resources/archetype-resources/docs/README.txt
index 7db3cb6..d45193a 100644
--- a/src/main/resources/archetype-resources/docs/README.txt
+++ b/src/main/resources/archetype-resources/docs/README.txt
@@ -21,14 +21,7 @@
About this archetype
-Turbine Version: Turbine 4.0-M2. Be aware and
- - keep groups/roles lower case
- - abstract classes and managers are included
- (because of some minor bugs in Fulcrum Security 1.1.0, which should be fixed in v 1.1.1/Turbine 4.0)
- - LogoutAction is included (fixed getUserFromSession)
- - om stub classes are included (until configurable in schema with Torque version 2.1)
- - (in SecureScreen) TurbineConfiguration returns a Commons configuration object, even if field is not assignable (will be fixed in Turbine 4.0, you can then assign e.g. to String instead)
-
+Turbine Version: Turbine 4.0-M2.
Quick Guide to using the new Turbine 4.0-M2 maven archetype
for skeleton application generation
@@ -36,7 +29,7 @@
You should have a local database installed and configured prior to
beginning the application setup below.
-
+
You can invoke the Maven archetype for turbine-webapp-4.0 from
the command line as shown below - please update values starting
with 'groupId' as appropriate.
@@ -53,10 +46,16 @@
-Dturbine_database_user=db_username \
-Dturbine_database_password=db_password \
-Dturbine_database_name=helloWorld \
- -Dgoals=generate-sources,sql:execute
+ -Dturbine_database_url=jdbc:mysql://localhost:3306/ \
+ -Dgoals=generate-sources, sql:execute
+Notes
-Note that the database URL (turbine_database_url=jdbc:mysql://localhost:3306/)
+When invoking archetype:generate, you can already set mvn commands and you can then skip them later.
+Be aware, when you set both mvn commands goals (-Dgoals=generate-sources, sql:execute), you have to create the database
+before invoking the archetype command.
+
+Note that the database URL (turbine_database_url)
will be appended with your database name
in the final pom.xml, so you do not need to specify that in
the configuration.
@@ -70,9 +69,6 @@
cd helloWorld
-You can skip the next two mvn commands, if you have already set the goals
-when invoking archetype:generate.
-
mvn generate-sources ## This will generate the OM layer and SQL
## code for creating the corresponding
## database tables
@@ -89,7 +85,7 @@
Open a web browser to http://localhost:8081/app
-Login should work with user admin/password.
+Login should work with user admin/password or user/password.
To enable application development in Eclipse, run the following command
and then import the project into Eclipse.
@@ -104,3 +100,16 @@
To test the application can be deployed by Eclipse, select the run
configuration "Run On Server" if you have a container configured with
your eclipse environment.
+
+Starting developing
+
+Be aware of settings and some smaller restrictions, which mostly will be fixed in the upcoming releases.
+
+- Keep groups/roles lower case (which should be fixed in Fulcrum Security 1.1.1/Turbine 4.0)
+- abstract classes and managers are included (because of some minor bugs in Fulcrum Security 1.1.0, same as above)
+- LogoutUser action is included (fix in Turbine 4.0, getUserFromSession)
+- LoginUser action is included (to check for anonymous user, may be fixed in future release)
+- OM (Torque Object Mapper) stub classes are included (until configurable in schema with Torque version 2.1)
+- TurbineConfiguration returns a Commons configuration object, even if field is not assignable (will be fixed in Turbine 4.0, you can then assign e.g. to String instead, cft. SecureScreen)
+- Database connection is done initially by default with JNDI. If you want to change it, check Torque.properties and jetty-env.xml.
+
diff --git a/src/main/resources/archetype-resources/docs/sample-mysql-data/application-data.sql b/src/main/resources/archetype-resources/docs/sample-mysql-data/_application-data.sql
similarity index 100%
rename from src/main/resources/archetype-resources/docs/sample-mysql-data/application-data.sql
rename to src/main/resources/archetype-resources/docs/sample-mysql-data/_application-data.sql
diff --git a/src/main/resources/archetype-resources/docs/sample-mysql-data/turbine-security-data.sql b/src/main/resources/archetype-resources/docs/sample-mysql-data/_turbine-security-data.sql
similarity index 92%
rename from src/main/resources/archetype-resources/docs/sample-mysql-data/turbine-security-data.sql
rename to src/main/resources/archetype-resources/docs/sample-mysql-data/_turbine-security-data.sql
index 8273075..db0775a 100644
--- a/src/main/resources/archetype-resources/docs/sample-mysql-data/turbine-security-data.sql
+++ b/src/main/resources/archetype-resources/docs/sample-mysql-data/_turbine-security-data.sql
@@ -4,6 +4,7 @@
## Torque will not autogenerate these files anymore - please run
## this SQL code maually to get your application up and running
##
+SET FOREIGN_KEY_CHECKS=0;
INSERT INTO TURBINE_USER (USER_ID,LOGIN_NAME,PASSWORD_VALUE,FIRST_NAME,LAST_NAME)
VALUES (1,'admin','password','','Admin');
@@ -12,7 +13,7 @@
VALUES (2,'user','password','','User');
INSERT INTO TURBINE_USER (USER_ID,LOGIN_NAME,PASSWORD_VALUE,FIRST_NAME,LAST_NAME)
- VALUES (2,'anon','nopw','','Anon');
+ VALUES (3,'anon','nopw','','Anon');
INSERT INTO `turbine_permission` (`PERMISSION_ID`, `PERMISSION_NAME`) VALUES
(2, 'Turbine'),
@@ -32,8 +33,8 @@
INSERT INTO `turbine_user_group_role` (`USER_ID`, `GROUP_ID`, `ROLE_ID`) VALUES
(1, 1, 1),
-(3, 1, 2),
(1, 2, 1),
-(2, 2, 2);
+(2, 2, 2),
+(2, 1, 2);
diff --git a/src/main/resources/archetype-resources/pom.xml b/src/main/resources/archetype-resources/pom.xml
index 582d96f..7db45ea 100644
--- a/src/main/resources/archetype-resources/pom.xml
+++ b/src/main/resources/archetype-resources/pom.xml
@@ -155,20 +155,19 @@
<password>${turbine_database_password}</password>
<onError>continue</onError>
<autocommit>true</autocommit>
+ <orderFile>ascending</orderFile>
<!-- this is mysql specific -->
- <sqlCommand>SET FOREIGN_KEY_CHECKS=0</sqlCommand>
<fileset>
- <basedir>${project.build.directory}/generated-sql/torque/${turbine_database_adapter}</basedir>
+ <basedir>${project.build.directory}/generated-sql/torque/mysql</basedir>
<!-- basedir>${basedir}/target/generated-sql</basedir -->
<includes>
<include>*.sql</include>
</includes>
</fileset>
<srcFiles>
- <srcFile>${basedir}/docs/sample-mysql-data/application-data.sql</srcFile>
- <srcFile>${basedir}/docs/sample-mysql-data/turbine-security-data.sql</srcFile>
+ <srcFile>${basedir}/docs/sample-mysql-data/_application-data.sql</srcFile>
+ <srcFile>${basedir}/docs/sample-mysql-data/_turbine-security-data.sql</srcFile>
</srcFiles>
- <sqlCommand>SET FOREIGN_KEY_CHECKS=1</sqlCommand>
</configuration>
<!-- update with your database driver dependency -->
diff --git a/src/main/resources/archetype-resources/src/main/java/modules/actions/ChangePasswordAction.java b/src/main/resources/archetype-resources/src/main/java/modules/actions/ChangePasswordAction.java
new file mode 100644
index 0000000..c8f4d1b
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/java/modules/actions/ChangePasswordAction.java
@@ -0,0 +1,95 @@
+package ${package}.modules.actions;
+
+#*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you 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.
+*#
+
+
+import org.apache.fulcrum.security.util.PasswordMismatchException;
+import org.apache.turbine.annotation.TurbineService;
+import org.apache.turbine.om.security.User;
+import org.apache.turbine.pipeline.PipelineData;
+import org.apache.turbine.services.security.SecurityService;
+import org.apache.turbine.util.RunData;
+import org.apache.velocity.context.Context;
+
+/**
+ * Change Password action.
+ *
+ */
+public class ChangePasswordAction extends SecureAction
+
+{
+
+ /** Injected service instance */
+ @TurbineService
+ private SecurityService security;
+
+
+ /**
+ * Implement this to add information to the context.
+ *
+ * @param data
+ * Turbine information.
+ * @param context
+ * Context for web pages.
+ * @exception Exception,
+ * a generic exception.
+ */
+ @Override
+ public void doPerform(PipelineData data)
+ throws Exception
+ {
+
+ User user = getRunData(data).getUser();
+
+ RunData rundata = getRunData(data);
+ String oldPassword = rundata.getParameters().getString("oldpassword", "");
+ String newPassword = rundata.getParameters().getString("newpassword", "");
+
+ try {
+ security.changePassword(user, oldPassword, newPassword);
+ rundata.setMessage("Password changed!");
+ }
+ catch (PasswordMismatchException e)
+ {
+ rundata.setMessage(e.getMessage());
+ rundata.setScreenTemplate("Password.vm");
+ }
+
+
+ }
+
+ /**
+ * Implement this to add information to the context.
+ *
+ * @param data
+ * Turbine information.
+ * @param context
+ * Context for web pages.
+ * @exception Exception,
+ * a generic exception.
+ */
+ @Override
+ public void doPerform(PipelineData data, Context context) throws Exception
+ {
+
+ context.put("success", "Password changed!!");
+ }
+
+}
diff --git a/src/main/resources/archetype-resources/src/main/java/modules/actions/LoginUser.java b/src/main/resources/archetype-resources/src/main/java/modules/actions/LoginUser.java
new file mode 100644
index 0000000..3018954
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/java/modules/actions/LoginUser.java
@@ -0,0 +1,114 @@
+package ${package}.modules.actions;
+
+#*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you 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.
+*#
+
+import org.apache.commons.configuration.Configuration;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.fulcrum.security.util.FulcrumSecurityException;
+import org.apache.fulcrum.security.util.UnknownEntityException;
+import org.apache.turbine.TurbineConstants;
+import org.apache.turbine.annotation.TurbineConfiguration;
+import org.apache.turbine.annotation.TurbineService;
+import org.apache.turbine.om.security.User;
+import org.apache.turbine.pipeline.PipelineData;
+import org.apache.turbine.services.security.SecurityService;
+import org.apache.turbine.util.RunData;
+
+/**
+ * This is where we authenticate the user logging into the system
+ * against a user in the database. If the user exists in the database
+ * that users last login time will be updated.
+ *
+ * @author <a href="mailto:mbryson@mont.mindspring.com">Dave Bryson</a>
+ * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
+ * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
+ * @author <a href="mailto:peter@courcoux.biz">Peter Courcoux</a>
+ * @version $Id: LoginUser.java 1725011 2016-01-16 17:38:47Z tv $
+ */
+public class LoginUser
+ extends org.apache.turbine.modules.actions.LoginUser
+{
+
+ /** Logging */
+ private static Log log = LogFactory.getLog(LoginUser.class);
+
+ /** Injected service instance */
+ @TurbineService
+ private SecurityService security;
+
+ /** Injected configuration instance */
+ @TurbineConfiguration
+ private Configuration conf;
+
+
+
+ /**
+ * Checks for anonymous user, else calls parent method.
+ *
+ * @param pipelineData Turbine information.
+ * @exception FulcrumSecurityException could not get instance of the
+ * anonymous user
+ */
+ @Override
+ public void doPerform(PipelineData pipelineData)
+ throws FulcrumSecurityException
+ {
+ RunData data = getRunData(pipelineData);
+ String username = data.getParameters().getString(LoginUser.CGI_USERNAME, "");
+
+ if (StringUtils.isEmpty(username))
+ {
+ return;
+ }
+
+ if (username.equals(security.getAnonymousUser().getName()))
+ {
+ data.setMessage("Anonymous user cannot login");
+ reset(data);
+ return;
+ }
+
+ super.doPerform(pipelineData);
+
+ }
+
+
+
+ private void reset(RunData data) throws UnknownEntityException {
+ User anonymousUser = security.getAnonymousUser();
+ data.setUser(anonymousUser);
+
+ if (StringUtils.isNotEmpty(conf.getString(TurbineConstants.TEMPLATE_LOGIN,"")))
+ {
+ // We're running in a templating solution
+ data.setScreenTemplate(
+ conf.getString(TurbineConstants.TEMPLATE_LOGIN));
+ }
+ else
+ {
+ data.setScreen(
+ conf.getString(TurbineConstants.SCREEN_LOGIN));
+ }
+ }
+
+}
+
diff --git a/src/main/resources/archetype-resources/src/main/java/modules/actions/LogoutUser.java b/src/main/resources/archetype-resources/src/main/java/modules/actions/LogoutUser.java
index bf16f31..2fea6dd 100644
--- a/src/main/resources/archetype-resources/src/main/java/modules/actions/LogoutUser.java
+++ b/src/main/resources/archetype-resources/src/main/java/modules/actions/LogoutUser.java
@@ -76,7 +76,7 @@
// Session validator did not run, so RunData is not populated
User user = data.getUserFromSession();
- if (!security.isAnonymousUser(user))
+ if (user != null && !security.isAnonymousUser(user))
{
// Make sure that the user has really logged in...
if (!user.hasLoggedIn())
diff --git a/src/main/resources/archetype-resources/src/main/java/modules/actions/SecureAction.java b/src/main/resources/archetype-resources/src/main/java/modules/actions/SecureAction.java
index 97e5aaf..f612181 100644
--- a/src/main/resources/archetype-resources/src/main/java/modules/actions/SecureAction.java
+++ b/src/main/resources/archetype-resources/src/main/java/modules/actions/SecureAction.java
@@ -55,12 +55,12 @@
// Get the Turbine ACL implementation
TurbineAccessControlList acl = getRunData(data).getACL();
- if (acl == null || !acl.hasRole("turbineadmin"))
+ if (acl == null || ! ( acl.hasRole("turbineuser") || acl.hasRole("turbineadmin") ) )
{
getRunData(data).setMessage("You do not have permission to access this action");
isAuthorized = false;
}
- else if (acl.hasRole("admin"))
+ else if ( acl.hasRole("turbineuser") || acl.hasRole("turbineadmin") )
{
isAuthorized = true;
}
diff --git a/src/main/resources/archetype-resources/src/main/java/modules/screens/Password.java b/src/main/resources/archetype-resources/src/main/java/modules/screens/Password.java
new file mode 100644
index 0000000..9028874
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/java/modules/screens/Password.java
@@ -0,0 +1,54 @@
+package ${package}.modules.screens;
+
+#*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you 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.
+*#
+
+import org.apache.fulcrum.security.model.turbine.TurbineAccessControlList;
+import org.apache.turbine.Turbine;
+import org.apache.turbine.TurbineConstants;
+import org.apache.turbine.annotation.TurbineConfiguration;
+import org.apache.turbine.annotation.TurbineService;
+import org.apache.turbine.modules.screens.VelocitySecureScreen;
+import org.apache.turbine.om.security.User;
+import org.apache.turbine.pipeline.PipelineData;
+import org.apache.turbine.services.security.SecurityService;
+import org.apache.velocity.context.Context;
+import org.apache.commons.configuration.Configuration;
+
+/**
+ * This class provides a sample extending a secured screen
+ */
+public class Password extends SecureScreen
+{
+
+ /**
+ * This method is called by the Turbine framework when the
+ * associated Velocity template, Index.vm is requested
+ *
+ * @param data the Turbine request data
+ * @param context the Velocity context
+ * @throws Exception a generic Exception
+ */
+ @Override
+ protected void doBuildTemplate(PipelineData data, Context context)
+ throws Exception
+ {
+
+ }
+}
diff --git a/src/main/resources/archetype-resources/src/main/java/modules/screens/SecureScreen.java b/src/main/resources/archetype-resources/src/main/java/modules/screens/SecureScreen.java
index 2e2a59f..74a4b49 100644
--- a/src/main/resources/archetype-resources/src/main/java/modules/screens/SecureScreen.java
+++ b/src/main/resources/archetype-resources/src/main/java/modules/screens/SecureScreen.java
@@ -18,6 +18,7 @@
* under the License.
*#
+
import org.apache.fulcrum.security.model.turbine.TurbineAccessControlList;
import org.apache.turbine.Turbine;
import org.apache.turbine.TurbineConstants;
@@ -55,13 +56,13 @@
// Get the Turbine ACL implementation
TurbineAccessControlList acl = getRunData(data).getACL();
- if (acl == null)
+ if (acl == null)
{
// commons configuration getProperty: prefix removed, the key for the value .. is an empty string, the result an object
getRunData(data).setScreenTemplate( (String) templateLogin.getProperty("") );
isAuthorized = false;
}
- else if (acl.hasRole("turbineadmin"))
+ else if (acl.hasRole("turbineuser") || acl.hasRole("turbineadmin"))
{
isAuthorized = true;
}
diff --git a/src/main/resources/archetype-resources/src/main/webapp/templates/navigations/Menu.vm b/src/main/resources/archetype-resources/src/main/webapp/templates/navigations/Menu.vm
index 1548d0b..4742b1f 100644
--- a/src/main/resources/archetype-resources/src/main/webapp/templates/navigations/Menu.vm
+++ b/src/main/resources/archetype-resources/src/main/webapp/templates/navigations/Menu.vm
@@ -23,9 +23,9 @@
<a href="#">Administration <i class="fa fa-caret-down"></i></a>
<div class="w3-dropdown-content w3-white w3-card-4">
## every user can change their password
- <a href="$link.setPage("user,Password.vm")">Update Password <i class="fa fa-unlock"></i></a>
+ <a href="$link.setPage("Password.vm")">Update Password <i class="fa fa-unlock"></i></a>
- #if ( $data.getACL().hasRole("admin") )
+ #if ( $data.getACL().hasRole("turbineadmin") )
<a href="$link.setPage("user,FluxUserList.vm")">User List <div class="w3-right"><i class="fa fa-users"></i></div></a>
<a href="$link.setPage("role,FluxRoleList.vm")">User Roles <div class="w3-right"><i class="fa fa-user-plus"></i></div></a>
<a href="$link.setPage("user,FluxUserForm.vm")?mode=insert">Add User <div class="w3-right"><i class="fa fa-user"></i></div></a>
@@ -34,6 +34,7 @@
</li>
<li class="w3-right"><a href="$link.setAction("LogoutUser")">Logout</a></li>
+
</nav>
#else
<nav class="w3-navbar w3-theme">
diff --git a/src/main/resources/archetype-resources/src/main/webapp/templates/screens/Login.vm b/src/main/resources/archetype-resources/src/main/webapp/templates/screens/Login.vm
index a2fa451..ff7d88a 100644
--- a/src/main/resources/archetype-resources/src/main/webapp/templates/screens/Login.vm
+++ b/src/main/resources/archetype-resources/src/main/webapp/templates/screens/Login.vm
@@ -30,12 +30,12 @@
## #end
<p/>
-
-
- <div class="w3-display-middle w3-card-8 w3-center w3-light-grey" style="max-width: 500px">
+ #if (! $data.user.hasLoggedIn())
- <form class="w3-container w3-light-grey" name="login" method="post" action="$link.setAction("LoginUser").setPage("TestSecure.vm")">
- <div class="w3-section">
+ <div class="w3-display-middle w3-card-8 w3-center w3-light-grey" style="max-width: 500px">
+
+ <form class="w3-container w3-light-grey" name="login" method="post" action="$link.setAction("LoginUser").setPage($data.templateInfo.screenTemplate)">
+ <div class="w3-section">
<p>
<!-- input class="w3-input w3-border" style="margin: auto; width: 200px;" placeholder="Username" type="text" name="$loginGroup.Username.Key" value="$!loginGroup.Username" -->
@@ -51,19 +51,20 @@
<p/>
- </div>
- </form>
+ </div>
+ </form>
- <div class="w3-container w3-border-top w3-padding-16 w3-light-grey">
- <span class="w3-right w3-padding w3-hide-small">Forgot <a href="#">password?</a></span>
- </div>
- ## Display System messages here if there are any
+ <div class="w3-container w3-border-top w3-padding-16 w3-light-grey">
+ <span class="w3-right w3-padding w3-hide-small">Forgot <a href="#">password?</a></span>
+ </div>
+
+ ## Display System messages here if there are any
#if($data.getMessage())
#info( $data.getMessage() ) <br/>
#end
</div>
-
+ #end
## $intake.declareGroups()
diff --git a/src/main/resources/archetype-resources/src/main/webapp/templates/screens/Password.vm b/src/main/resources/archetype-resources/src/main/webapp/templates/screens/Password.vm
new file mode 100644
index 0000000..c5c2b83
--- /dev/null
+++ b/src/main/resources/archetype-resources/src/main/webapp/templates/screens/Password.vm
@@ -0,0 +1,56 @@
+## Licensed to the Apache Software Foundation (ASF) under one
+## or more contributor license agreements. See the NOTICE file
+## distributed with this work for additional information
+## regarding copyright ownership. The ASF licenses this file
+## to you 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.
+
+
+ <div class="w3-display-middle w3-card-8 w3-center w3-light-grey" style="max-width: 500px">
+
+ <form class="w3-container w3-light-grey" name="password_change" method="post" action="$link.setAction("ChangePasswordAction").setPage("Index.vm")">
+ <div class="w3-section">
+
+
+ <p>
+ <input class="w3-input w3-border" style="margin: auto; width: 200px;" placeholder="Old Password" type="password" name="oldpassword" value="" tabindex="2" autocomplete="off">
+ </p>
+
+ <p>
+ <input class="w3-input w3-border" style="margin: auto; width: 200px;" placeholder="New Password" type="password" name="newpassword" value="" tabindex="2" autocomplete="off">
+ </p>
+
+ <button type="submit" name="submit" id="submit" value="eventSubmit_doPerform" class="w3-ripple">Change Password</button>
+
+ <button type="button" name="cancel" id="cancel" value="cancel" class="w3-ripple" onCLick="doCancel()">Cancel</button>
+
+ <script>
+ function doCancel() {
+ location.href="$link.setPage('TestSecure.vm')";
+ return false;
+ }
+ </script>
+
+ <p/>
+
+
+ </div>
+ </form>
+
+
+ ## Display System messages here if there are any
+ #if($data.getMessage())
+ #info( $data.getMessage() ) <br/>
+ #end
+
+ </div>
\ No newline at end of file