From 6f94cc680f45c0e5902d57c035fc0cca23eb6596 Mon Sep 17 00:00:00 2001
From: Alinga Yeung <Alinga.Yeung@nrc-cnrc.gc.ca>
Date: Tue, 8 Sep 2015 17:35:47 -0700
Subject: [PATCH] Story 1840. Initial setup of this module with the command
 line framework. The 'List' command appears to work.

---
 projects/cadcAccessControl-Admin/.gitignore   |   3 +
 projects/cadcAccessControl-Admin/build.xml    | 112 ++++++++
 .../cadcAccessControl-Admin/scripts/userAdmin |   5 +
 .../ca/nrc/cadc/ac/admin/AbstractCommand.java |  48 ++++
 .../src/ca/nrc/cadc/ac/admin/Approve.java     |  32 +++
 .../ca/nrc/cadc/ac/admin/CmdLineParser.java   | 263 ++++++++++++++++++
 .../src/ca/nrc/cadc/ac/admin/List.java        |  54 ++++
 .../src/ca/nrc/cadc/ac/admin/Main.java        | 167 +++++++++++
 .../src/ca/nrc/cadc/ac/admin/Reject.java      |  31 +++
 .../ca/nrc/cadc/ac/admin/UsageException.java  |  46 +++
 .../cadcAccessControl-Admin/src/userAdmin.mf  |   1 +
 11 files changed, 762 insertions(+)
 create mode 100644 projects/cadcAccessControl-Admin/.gitignore
 create mode 100644 projects/cadcAccessControl-Admin/build.xml
 create mode 100755 projects/cadcAccessControl-Admin/scripts/userAdmin
 create mode 100644 projects/cadcAccessControl-Admin/src/ca/nrc/cadc/ac/admin/AbstractCommand.java
 create mode 100644 projects/cadcAccessControl-Admin/src/ca/nrc/cadc/ac/admin/Approve.java
 create mode 100644 projects/cadcAccessControl-Admin/src/ca/nrc/cadc/ac/admin/CmdLineParser.java
 create mode 100644 projects/cadcAccessControl-Admin/src/ca/nrc/cadc/ac/admin/List.java
 create mode 100644 projects/cadcAccessControl-Admin/src/ca/nrc/cadc/ac/admin/Main.java
 create mode 100644 projects/cadcAccessControl-Admin/src/ca/nrc/cadc/ac/admin/Reject.java
 create mode 100644 projects/cadcAccessControl-Admin/src/ca/nrc/cadc/ac/admin/UsageException.java
 create mode 100644 projects/cadcAccessControl-Admin/src/userAdmin.mf

diff --git a/projects/cadcAccessControl-Admin/.gitignore b/projects/cadcAccessControl-Admin/.gitignore
new file mode 100644
index 00000000..ca203d09
--- /dev/null
+++ b/projects/cadcAccessControl-Admin/.gitignore
@@ -0,0 +1,3 @@
+/bin
+/bin1
+/build
diff --git a/projects/cadcAccessControl-Admin/build.xml b/projects/cadcAccessControl-Admin/build.xml
new file mode 100644
index 00000000..4163c947
--- /dev/null
+++ b/projects/cadcAccessControl-Admin/build.xml
@@ -0,0 +1,112 @@
+<!--
+************************************************************************
+*******************  CANADIAN ASTRONOMY DATA CENTRE  *******************
+**************  CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES  **************
+*
+*  (c) 2009.                            (c) 2009.
+*  Government of Canada                 Gouvernement du Canada
+*  National Research Council            Conseil national de recherches
+*  Ottawa, Canada, K1A 0R6              Ottawa, Canada, K1A 0R6
+*  All rights reserved                  Tous droits réservés
+*                                       
+*  NRC disclaims any warranties,        Le CNRC dénie toute garantie
+*  expressed, implied, or               énoncée, implicite ou légale,
+*  statutory, of any kind with          de quelque nature que ce
+*  respect to the software,             soit, concernant le logiciel,
+*  including without limitation         y compris sans restriction
+*  any warranty of merchantability      toute garantie de valeur
+*  or fitness for a particular          marchande ou de pertinence
+*  purpose. NRC shall not be            pour un usage particulier.
+*  liable in any event for any          Le CNRC ne pourra en aucun cas
+*  damages, whether direct or           être tenu responsable de tout
+*  indirect, special or general,        dommage, direct ou indirect,
+*  consequential or incidental,         particulier ou général,
+*  arising from the use of the          accessoire ou fortuit, résultant
+*  software.  Neither the name          de l'utilisation du logiciel. Ni
+*  of the National Research             le nom du Conseil National de
+*  Council of Canada nor the            Recherches du Canada ni les noms
+*  names of its contributors may        de ses  participants ne peuvent
+*  be used to endorse or promote        être utilisés pour approuver ou
+*  products derived from this           promouvoir les produits dérivés
+*  software without specific prior      de ce logiciel sans autorisation
+*  written permission.                  préalable et particulière
+*                                       par écrit.
+*                                       
+*  This file is part of the             Ce fichier fait partie du projet
+*  OpenCADC project.                    OpenCADC.
+*                                       
+*  OpenCADC is free software:           OpenCADC est un logiciel libre ;
+*  you can redistribute it and/or       vous pouvez le redistribuer ou le
+*  modify it under the terms of         modifier suivant les termes de
+*  the GNU Affero General Public        la “GNU Affero General Public
+*  License as published by the          License” telle que publiée
+*  Free Software Foundation,            par la Free Software Foundation
+*  either version 3 of the              : soit la version 3 de cette
+*  License, or (at your option)         licence, soit (à votre gré)
+*  any later version.                   toute version ultérieure.
+*                                       
+*  OpenCADC is distributed in the       OpenCADC est distribué
+*  hope that it will be useful,         dans l’espoir qu’il vous
+*  but WITHOUT ANY WARRANTY;            sera utile, mais SANS AUCUNE
+*  without even the implied             GARANTIE : sans même la garantie
+*  warranty of MERCHANTABILITY          implicite de COMMERCIALISABILITÉ
+*  or FITNESS FOR A PARTICULAR          ni d’ADÉQUATION À UN OBJECTIF
+*  PURPOSE.  See the GNU Affero         PARTICULIER. Consultez la Licence
+*  General Public License for           Générale Publique GNU Affero
+*  more details.                        pour plus de détails.
+*                                       
+*  You should have received             Vous devriez avoir reçu une
+*  a copy of the GNU Affero             copie de la Licence Générale
+*  General Public License along         Publique GNU Affero avec
+*  with OpenCADC.  If not, see          OpenCADC ; si ce n’est
+*  <http://www.gnu.org/licenses/>.      pas le cas, consultez :
+*                                       <http://www.gnu.org/licenses/>.
+*
+*  $Revision: 4 $
+*
+************************************************************************
+-->
+
+    
+<project default="build" basedir=".">
+
+    <property environment="env"/>
+    <property file="local.build.properties" />
+    
+    <property file="${env.A}/compilers/setup.ant.java.properties" />
+    <import file="${env.A}/compilers/setup.ant.java.targets.xml"/>
+
+    <!-- developer convenience: place for extra targets and properties -->
+    <import file="extras.xml" optional="true" />
+
+    <property file="local.build.properties" />
+    
+    <property name="project" value="userAdmin" />
+
+    <!-- JAR files to be included in classpath and war file -->
+    <property name="cadcAccessControl"		value="${lib}/cadcAccessControl.jar" />
+    <property name="cadcAccessControl-Server"	value="${lib}/cadcAccessControl-Server.jar" />
+    <property name="cadcUtil"			value="${lib}/cadcUtil.jar" />
+    <property name="javaUtil"			value="${lib}/javaUtil.jar" />
+    <property name="log4j"			value="${ext.lib}/log4j.jar" />
+    <property name="commons-logging"		value="${ext.lib}/commons-logging.jar" />
+    <property name="jconn3"			value="${ext.lib}/jconn3.jar" />
+    <property name="spring"			value="${ext.lib}/spring.jar" />
+    <property name="unboundid"			value="${ext.lib}/unboundid-ldapsdk-se.jar" />
+    
+    <property name="cadc"       value="${cadcAccessControl}:${cadcAccessControl-Server}:${cadcUtil}:${javaUtil}" />
+    <property name="external"   value="${unboundid}:${spring}:${commons-logging}:${jconn3}:${log4j}" />
+
+    <property name="jars"       value="${cadc}:${external}" />
+    
+    <target name="build" depends="simpleJar" />
+
+    <!-- JAR files needed to run the test suite -->
+    <property name="junit"          value="${ext.dev}/junit.jar" />
+    <property name="easymock"       value="${ext.dev}/easymock.jar" />
+    <property name="em_extras" value="${ext.dev}/objenesis.jar:${ext.dev}/cglib.jar:${ext.dev}/asm.jar" />
+
+    <property name="testingJars" value="${junit}:${easymock}:${em_extras}" />
+    
+
+</project>
diff --git a/projects/cadcAccessControl-Admin/scripts/userAdmin b/projects/cadcAccessControl-Admin/scripts/userAdmin
new file mode 100755
index 00000000..d766b8d9
--- /dev/null
+++ b/projects/cadcAccessControl-Admin/scripts/userAdmin
@@ -0,0 +1,5 @@
+#!/bin/tcsh -f
+
+source ${DEFAULT_CONFIG_DIR}/JavaSystemProps.csh || exit $status
+
+java -Xmx128m ${JAVA_SYSTEM_PROPS} -jar ${CADC_ROOT}/lib/userAdmin.jar $*:q
diff --git a/projects/cadcAccessControl-Admin/src/ca/nrc/cadc/ac/admin/AbstractCommand.java b/projects/cadcAccessControl-Admin/src/ca/nrc/cadc/ac/admin/AbstractCommand.java
new file mode 100644
index 00000000..40193a28
--- /dev/null
+++ b/projects/cadcAccessControl-Admin/src/ca/nrc/cadc/ac/admin/AbstractCommand.java
@@ -0,0 +1,48 @@
+package ca.nrc.cadc.ac.admin;
+
+import java.io.PrintStream;
+import java.security.Principal;
+import java.security.PrivilegedAction;
+
+import org.apache.log4j.Logger;
+
+import ca.nrc.cadc.ac.server.PluginFactory;
+import ca.nrc.cadc.ac.server.UserPersistence;
+
+/**
+ * Govern the methods that each access control admin command has to support.
+ * @author yeunga
+ *
+ */
+public abstract class AbstractCommand implements PrivilegedAction<Object>
+{
+    private static final Logger log = Logger.getLogger(AbstractCommand.class);
+
+    protected PrintStream systemOut = System.out;
+    protected PrintStream systemErr = System.err;
+	   
+    /**
+     * Set the system out.
+     * @param printStream
+     */
+    public void setSystemOut(PrintStream printStream)
+    {
+        this.systemOut = printStream;
+    }
+    
+    /**
+     * Set the system err.
+     * @param printStream
+     */
+    public void setSystemErr(PrintStream printStream)
+    {
+        this.systemErr = printStream;
+    }
+
+    @SuppressWarnings("unchecked")
+    protected <T extends Principal> UserPersistence<T> getUserPersistence()
+    {
+        PluginFactory pluginFactory = new PluginFactory();
+        return pluginFactory.getUserPersistence();
+    }
+}
diff --git a/projects/cadcAccessControl-Admin/src/ca/nrc/cadc/ac/admin/Approve.java b/projects/cadcAccessControl-Admin/src/ca/nrc/cadc/ac/admin/Approve.java
new file mode 100644
index 00000000..290cbaa7
--- /dev/null
+++ b/projects/cadcAccessControl-Admin/src/ca/nrc/cadc/ac/admin/Approve.java
@@ -0,0 +1,32 @@
+package ca.nrc.cadc.ac.admin;
+
+import org.apache.log4j.Logger;
+
+/**
+ * This class approves the specified pending user by changing the user
+ * from a pending user to an active user in the LDAP server.
+ * @author yeunga
+ *
+ */
+public class Approve extends AbstractCommand 
+{
+    private static final Logger log = Logger.getLogger(Approve.class);
+
+	private String userID;
+	
+	/**
+	 * Constructor
+	 * @param userID Id of the pending user to be approved
+	 */
+    public Approve(final String userID)
+    {
+    	this.userID = userID;
+    }
+    
+	@Override
+	public Object run() 
+	{
+		// TODO Auto-generated method stub
+        return new Object();
+	}
+}
diff --git a/projects/cadcAccessControl-Admin/src/ca/nrc/cadc/ac/admin/CmdLineParser.java b/projects/cadcAccessControl-Admin/src/ca/nrc/cadc/ac/admin/CmdLineParser.java
new file mode 100644
index 00000000..9a104225
--- /dev/null
+++ b/projects/cadcAccessControl-Admin/src/ca/nrc/cadc/ac/admin/CmdLineParser.java
@@ -0,0 +1,263 @@
+/*
+ ************************************************************************
+ *******************  CANADIAN ASTRONOMY DATA CENTRE  *******************
+ **************  CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES  **************
+ *
+ *  (c) 2014.                            (c) 2014.
+ *  Government of Canada                 Gouvernement du Canada
+ *  National Research Council            Conseil national de recherches
+ *  Ottawa, Canada, K1A 0R6              Ottawa, Canada, K1A 0R6
+ *  All rights reserved                  Tous droits réservés
+ *
+ *  NRC disclaims any warranties,        Le CNRC dénie toute garantie
+ *  expressed, implied, or               énoncée, implicite ou légale,
+ *  statutory, of any kind with          de quelque nature que ce
+ *  respect to the software,             soit, concernant le logiciel,
+ *  including without limitation         y compris sans restriction
+ *  any warranty of merchantability      toute garantie de valeur
+ *  or fitness for a particular          marchande ou de pertinence
+ *  purpose. NRC shall not be            pour un usage particulier.
+ *  liable in any event for any          Le CNRC ne pourra en aucun cas
+ *  damages, whether direct or           être tenu responsable de tout
+ *  indirect, special or general,        dommage, direct ou indirect,
+ *  consequential or incidental,         particulier ou général,
+ *  arising from the use of the          accessoire ou fortuit, résultant
+ *  software.  Neither the name          de l'utilisation du logiciel. Ni
+ *  of the National Research             le nom du Conseil National de
+ *  Council of Canada nor the            Recherches du Canada ni les noms
+ *  names of its contributors may        de ses  participants ne peuvent
+ *  be used to endorse or promote        être utilisés pour approuver ou
+ *  products derived from this           promouvoir les produits dérivés
+ *  software without specific prior      de ce logiciel sans autorisation
+ *  written permission.                  préalable et particulière
+ *                                       par écrit.
+ *
+ *  This file is part of the             Ce fichier fait partie du projet
+ *  OpenCADC project.                    OpenCADC.
+ *
+ *  OpenCADC is free software:           OpenCADC est un logiciel libre ;
+ *  you can redistribute it and/or       vous pouvez le redistribuer ou le
+ *  modify it under the terms of         modifier suivant les termes de
+ *  the GNU Affero General Public        la “GNU Affero General Public
+ *  License as published by the          License” telle que publiée
+ *  Free Software Foundation,            par la Free Software Foundation
+ *  either version 3 of the              : soit la version 3 de cette
+ *  License, or (at your option)         licence, soit (à votre gré)
+ *  any later version.                   toute version ultérieure.
+ *
+ *  OpenCADC is distributed in the       OpenCADC est distribué
+ *  hope that it will be useful,         dans l’espoir qu’il vous
+ *  but WITHOUT ANY WARRANTY;            sera utile, mais SANS AUCUNE
+ *  without even the implied             GARANTIE : sans même la garantie
+ *  warranty of MERCHANTABILITY          implicite de COMMERCIALISABILITÉ
+ *  or FITNESS FOR A PARTICULAR          ni d’ADÉQUATION À UN OBJECTIF
+ *  PURPOSE.  See the GNU Affero         PARTICULIER. Consultez la Licence
+ *  General Public License for           Générale Publique GNU Affero
+ *  more details.                        pour plus de détails.
+ *
+ *  You should have received             Vous devriez avoir reçu une
+ *  a copy of the GNU Affero             copie de la Licence Générale
+ *  General Public License along         Publique GNU Affero avec
+ *  with OpenCADC.  If not, see          OpenCADC ; si ce n’est
+ *  <http://www.gnu.org/licenses/>.      pas le cas, consultez :
+ *                                       <http://www.gnu.org/licenses/>.
+ *
+ *  $Revision: 4 $
+ *
+ ************************************************************************
+ */
+
+ package ca.nrc.cadc.ac.admin;
+
+import java.security.cert.CertificateException;
+
+import javax.security.auth.Subject;
+
+import org.apache.log4j.Logger;
+
+import ca.nrc.cadc.auth.CertCmdArgUtil;
+import ca.nrc.cadc.auth.SSLUtil;
+import ca.nrc.cadc.util.ArgumentMap;
+
+
+
+/**
+ * This class parses the command line input arguments.
+ */
+public class CmdLineParser 
+{
+    private static Logger log = Logger.getLogger(CmdLineParser.class);
+
+    // no need to proceed further if false
+    private boolean proceed = true;
+    private String appName = "";
+    private AbstractCommand command;
+    private Subject subject;
+
+    /**
+     * Default constructor.
+     */
+    public CmdLineParser(final String name) 
+    {
+    	this.appName = name;
+    }
+    
+    /**
+     * Return proceed status.
+     * @return true  program should proceed with further processing
+     *         false program should not proceed further
+     */
+    public boolean proceed()
+    {
+        return this.proceed;
+    }
+
+    /**
+     * Get the user admin command to be performed.
+     * @return user admin command
+     */
+    public AbstractCommand getCommand()
+    {
+    	return this.command;
+    }
+    
+    /**
+     * Get the subject representing the user executing this user admin tool.
+     */
+    public Subject getSubject()
+    {
+    	return this.subject;
+    }
+    
+    protected boolean isValid(final ArgumentMap am) throws UsageException
+    {
+    	int levelCount = 0;
+    	int cmdCount = 0;
+    	
+        // only one command is allowed per command line
+    	if (am.isSet("list"))
+    	{
+    		this.command = new List();
+    		cmdCount++;
+    	}
+
+    	if (am.isSet("list-pending"))
+    	{
+    		this.command = new ListPending();
+    		cmdCount++;
+    	}
+    	
+    	String userID = am.getValue("view");
+    	if ((userID != null	) && (!userID.equalsIgnoreCase("true")))
+    	{
+    		this.command = new View(userID);
+    		cmdCount++;
+    	}
+    	
+        userID = am.getValue("reject");
+    	if ((userID != null	) && (!userID.equalsIgnoreCase("true")))
+    	{
+    		this.command = new Reject(userID);
+    		cmdCount++;
+    	}
+    	
+        userID = am.getValue("approve");
+    	if ((userID != null	) && (!userID.equalsIgnoreCase("true")))
+    	{
+    		this.command = new Approve(userID);
+    		cmdCount++;
+    	}
+    	
+        // only one log level is allowed 
+    	if (am.isSet("v") || am.isSet("verbose"))
+    	{
+    		levelCount++;
+    	}
+
+    	if (am.isSet("d") || am.isSet("debug"))
+    	{
+    		levelCount++;
+    	}
+                    	
+    	if ((cmdCount == 1) && (levelCount <2))
+    	{
+    		return true;
+    	}
+    	else
+    	{
+    		String msg = "";
+    		if (cmdCount > 1)
+    		{
+    		    msg = "Only one command can be specified.\n";
+    		}
+    		
+            if (levelCount == 2)
+    		{
+                msg = "--verbose and --debug are mutually exclusive options\n";
+    		}
+            
+    		throw new UsageException(msg);
+    	}
+    }
+    
+    /**
+     * Parse the command line arguments.
+     * @param args command line arguments
+     * @throws UsageException Error in command line
+     * @throws CertificateException 
+     */
+    public void parse(final String[] args) throws UsageException, CertificateException
+    {
+        ArgumentMap am = new ArgumentMap( args );
+        this.proceed = false;
+
+        if (!am.isSet("h") && !am.isSet("help") && isValid(am))
+        {
+            Subject subject = CertCmdArgUtil.initSubject(am, true);
+            try 
+            {
+    			SSLUtil.validateSubject(subject, null);
+    			this.subject = subject;
+                this.proceed = true;
+    		} 
+            catch (CertificateException e) 
+    		{
+            	if (am.isSet("list") || am.isSet("list-pending"))
+            	{
+            		// we can use anonymous subject
+            		this.proceed = true;
+            	}
+            	else
+            	{
+    				throw e;
+            	}
+    		}
+        }
+    }    
+
+    /**
+     * Provide the default command line usage. 
+     */
+    public String getUsage()
+    {
+    	StringBuilder sb = new StringBuilder();
+    	sb.append("\n");
+    	sb.append("Usage: " + this.appName + " <command> [-v|--verbose|-d|--debug] [-h|--help]\n");
+    	sb.append("Where command is\n");
+    	sb.append("--list               :list users in the Users tree\n");
+    	sb.append("                     :can be executed as an anonymous user\n");
+    	sb.append("--list-pending       :list users in the UserRequests tree\n");
+    	sb.append("                     :except those with nsaccountlock=true\n");
+    	sb.append("                     :can be executed as an anonymous user\n");
+    	sb.append("--view=<userid>      :print the entire details of the user\n");
+    	sb.append("--approve=<userid>   :delete the user from the UserRequests tree\n");
+    	sb.append("                     :by setting nsaccount=true, and insert it to the Users tree\n");
+    	sb.append("--reject=<userid>    :delete the user from the UserRequests tree\n");
+    	sb.append("\n");
+    	sb.append("-v|--verbose         : Verbose mode print progress and error messages\n");
+    	sb.append("-d|--debug           : Debug mode print all the logging messages\n");
+    	sb.append("-h|--help            : Print this message and exit\n");
+    	return sb.toString();
+    }
+
+}
diff --git a/projects/cadcAccessControl-Admin/src/ca/nrc/cadc/ac/admin/List.java b/projects/cadcAccessControl-Admin/src/ca/nrc/cadc/ac/admin/List.java
new file mode 100644
index 00000000..beb96c2a
--- /dev/null
+++ b/projects/cadcAccessControl-Admin/src/ca/nrc/cadc/ac/admin/List.java
@@ -0,0 +1,54 @@
+package ca.nrc.cadc.ac.admin;
+
+import java.security.AccessControlException;
+import java.security.Principal;
+import java.util.Collection;
+
+import org.apache.log4j.Logger;
+
+import ca.nrc.cadc.ac.User;
+import ca.nrc.cadc.ac.server.UserPersistence;
+import ca.nrc.cadc.net.TransientException;
+
+/**
+ * This class provides a list of all active users in the LDAP server.
+ * @author yeunga
+ *
+ */
+public class List extends AbstractCommand 
+{	
+    private static final Logger log = Logger.getLogger(List.class);
+
+    /**
+	 * Constructor
+	 */
+    public List()
+    {
+    }
+    
+	@Override
+	public Object run() 
+	{
+		try 
+		{
+	        final UserPersistence<Principal> userPersistence = getUserPersistence();
+			Collection<User<Principal>> users = userPersistence.getUsers();
+			
+	        for (User<Principal> user : users)
+	        {
+	        	systemOut.println(user.getUserID().getName());
+	        }
+		} 
+		catch (AccessControlException e) 
+		{
+            log.error(e.getMessage(), e);
+		} 
+		catch (TransientException e) 
+		{
+            String message = "Internal Transient Error: " + e.getMessage();
+            log.error(message, e);
+		}
+		
+        return null;
+	}
+}
diff --git a/projects/cadcAccessControl-Admin/src/ca/nrc/cadc/ac/admin/Main.java b/projects/cadcAccessControl-Admin/src/ca/nrc/cadc/ac/admin/Main.java
new file mode 100644
index 00000000..27f35880
--- /dev/null
+++ b/projects/cadcAccessControl-Admin/src/ca/nrc/cadc/ac/admin/Main.java
@@ -0,0 +1,167 @@
+/*
+ ************************************************************************
+ *******************  CANADIAN ASTRONOMY DATA CENTRE  *******************
+ **************  CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES  **************
+ *
+ *  (c) 2014.                            (c) 2014.
+ *  Government of Canada                 Gouvernement du Canada
+ *  National Research Council            Conseil national de recherches
+ *  Ottawa, Canada, K1A 0R6              Ottawa, Canada, K1A 0R6
+ *  All rights reserved                  Tous droits réservés
+ *
+ *  NRC disclaims any warranties,        Le CNRC dénie toute garantie
+ *  expressed, implied, or               énoncée, implicite ou légale,
+ *  statutory, of any kind with          de quelque nature que ce
+ *  respect to the software,             soit, concernant le logiciel,
+ *  including without limitation         y compris sans restriction
+ *  any warranty of merchantability      toute garantie de valeur
+ *  or fitness for a particular          marchande ou de pertinence
+ *  purpose. NRC shall not be            pour un usage particulier.
+ *  liable in any event for any          Le CNRC ne pourra en aucun cas
+ *  damages, whether direct or           être tenu responsable de tout
+ *  indirect, special or general,        dommage, direct ou indirect,
+ *  consequential or incidental,         particulier ou général,
+ *  arising from the use of the          accessoire ou fortuit, résultant
+ *  software.  Neither the name          de l'utilisation du logiciel. Ni
+ *  of the National Research             le nom du Conseil National de
+ *  Council of Canada nor the            Recherches du Canada ni les noms
+ *  names of its contributors may        de ses  participants ne peuvent
+ *  be used to endorse or promote        être utilisés pour approuver ou
+ *  products derived from this           promouvoir les produits dérivés
+ *  software without specific prior      de ce logiciel sans autorisation
+ *  written permission.                  préalable et particulière
+ *                                       par écrit.
+ *
+ *  This file is part of the             Ce fichier fait partie du projet
+ *  OpenCADC project.                    OpenCADC.
+ *
+ *  OpenCADC is free software:           OpenCADC est un logiciel libre ;
+ *  you can redistribute it and/or       vous pouvez le redistribuer ou le
+ *  modify it under the terms of         modifier suivant les termes de
+ *  the GNU Affero General Public        la “GNU Affero General Public
+ *  License as published by the          License” telle que publiée
+ *  Free Software Foundation,            par la Free Software Foundation
+ *  either version 3 of the              : soit la version 3 de cette
+ *  License, or (at your option)         licence, soit (à votre gré)
+ *  any later version.                   toute version ultérieure.
+ *
+ *  OpenCADC is distributed in the       OpenCADC est distribué
+ *  hope that it will be useful,         dans l’espoir qu’il vous
+ *  but WITHOUT ANY WARRANTY;            sera utile, mais SANS AUCUNE
+ *  without even the implied             GARANTIE : sans même la garantie
+ *  warranty of MERCHANTABILITY          implicite de COMMERCIALISABILITÉ
+ *  or FITNESS FOR A PARTICULAR          ni d’ADÉQUATION À UN OBJECTIF
+ *  PURPOSE.  See the GNU Affero         PARTICULIER. Consultez la Licence
+ *  General Public License for           Générale Publique GNU Affero
+ *  more details.                        pour plus de détails.
+ *
+ *  You should have received             Vous devriez avoir reçu une
+ *  a copy of the GNU Affero             copie de la Licence Générale
+ *  General Public License along         Publique GNU Affero avec
+ *  with OpenCADC.  If not, see          OpenCADC ; si ce n’est
+ *  <http://www.gnu.org/licenses/>.      pas le cas, consultez :
+ *                                       <http://www.gnu.org/licenses/>.
+ *
+ *  $Revision: 4 $
+ *
+ ************************************************************************
+ */
+
+package ca.nrc.cadc.ac.admin;
+
+import java.io.PrintStream;
+import java.security.cert.CertificateException;
+
+import javax.security.auth.Subject;
+
+import org.apache.log4j.Logger;
+
+import ca.nrc.cadc.util.LoggerUtil;
+
+/**
+ * A command line admin tool for LDAP users.
+ * 
+ * @author yeunga
+ *
+ */
+public class Main
+{
+    private static Logger log = Logger.getLogger(Main.class);
+    
+	private static final String APP_NAME = "userAdmin";
+    private static PrintStream systemOut = System.out;
+    private static PrintStream systemErr = System.err;
+ 
+    /**
+     * Set the system out.
+     * @param printStream
+     */
+    public static void setSystemOut(PrintStream printStream)
+    {
+        systemOut = printStream;
+    }
+    
+    /**
+     * Set the system err.
+     * @param printStream
+     */
+    public static void setSystemErr(PrintStream printStream)
+    {
+        systemErr = printStream;
+    }
+
+    /**
+     * Execute the specified utility.
+     * @param args   The arguments passed in to this programme.
+     */
+    public static void main(String[] args)
+    {
+    	CmdLineParser parser = new CmdLineParser(APP_NAME);
+    	
+        try
+        {
+            LoggerUtil.initialize(new String[]
+                    { "ca.nrc.cadc.ac", "ca.nrc.cadc.auth", "ca.nrc.cadc.util" },
+                    args);
+        	parser.parse(args);
+        	if (parser.proceed())
+        	{  
+        		AbstractCommand command = parser.getCommand();
+            	command.setSystemOut(systemOut);
+            	command.setSystemErr(systemErr);
+        		if (parser.getSubject() == null)
+        		{
+        			// no credential, but command works with an anonymous user
+        			command.run();
+        		}
+        		else
+        		{
+        			// has credential, execute the command 
+        			Subject.doAs(parser.getSubject(), command);
+        		}
+        	}
+        	else
+        	{
+        		systemOut.println(parser.getUsage());
+        	}
+        }
+        catch(UsageException e)
+        {
+            systemErr.println("ERROR: " + e.getMessage());
+    		systemOut.println(parser.getUsage());
+            System.exit(0);
+        }
+        catch(CertificateException e)
+        {
+            systemErr.println("ERROR: " + e.getMessage());
+            e.printStackTrace(systemErr);
+            System.exit(0);
+        }
+        catch(Throwable t)
+        {
+            systemErr.println("ERROR: " + t.getMessage());
+            t.printStackTrace(systemErr);
+            System.exit(-1);
+        }
+    }
+}
diff --git a/projects/cadcAccessControl-Admin/src/ca/nrc/cadc/ac/admin/Reject.java b/projects/cadcAccessControl-Admin/src/ca/nrc/cadc/ac/admin/Reject.java
new file mode 100644
index 00000000..7125f4d9
--- /dev/null
+++ b/projects/cadcAccessControl-Admin/src/ca/nrc/cadc/ac/admin/Reject.java
@@ -0,0 +1,31 @@
+package ca.nrc.cadc.ac.admin;
+
+import org.apache.log4j.Logger;
+
+/**
+ * This class deletes the specified pending user from the LDAP server.
+ * @author yeunga
+ *
+ */
+public class Reject extends AbstractCommand 
+{
+    private static final Logger log = Logger.getLogger(Reject.class);
+
+	private String userID;
+	
+	/**
+	 * Constructor
+	 * @param userID Id of the pending user to be deleted
+	 */
+    public Reject(final String userID)
+    {
+    	this.userID = userID;
+    }
+    
+	@Override
+	public Object run() 
+	{
+		// TODO Auto-generated method stub
+        return new Object();
+	}
+}
diff --git a/projects/cadcAccessControl-Admin/src/ca/nrc/cadc/ac/admin/UsageException.java b/projects/cadcAccessControl-Admin/src/ca/nrc/cadc/ac/admin/UsageException.java
new file mode 100644
index 00000000..606021c9
--- /dev/null
+++ b/projects/cadcAccessControl-Admin/src/ca/nrc/cadc/ac/admin/UsageException.java
@@ -0,0 +1,46 @@
+/*
+ ************************************************************************
+ ****  C A N A D I A N   A S T R O N O M Y   D A T A   C E N T R E  *****
+ *
+ * (c) 2013.                            (c) 2013.
+ * National Research Council            Conseil national de recherches
+ * Ottawa, Canada, K1A 0R6              Ottawa, Canada, K1A 0R6
+ * All rights reserved                  Tous droits reserves
+ *
+ * NRC disclaims any warranties         Le CNRC denie toute garantie
+ * expressed, implied, or statu-        enoncee, implicite ou legale,
+ * tory, of any kind with respect       de quelque nature que se soit,
+ * to the software, including           concernant le logiciel, y com-
+ * without limitation any war-          pris sans restriction toute
+ * ranty of merchantability or          garantie de valeur marchande
+ * fitness for a particular pur-        ou de pertinence pour un usage
+ * pose.  NRC shall not be liable       particulier.  Le CNRC ne
+ * in any event for any damages,        pourra en aucun cas etre tenu
+ * whether direct or indirect,          responsable de tout dommage,
+ * special or general, consequen-       direct ou indirect, particul-
+ * tial or incidental, arising          ier ou general, accessoire ou
+ * from the use of the software.        fortuit, resultant de l'utili-
+ *                                      sation du logiciel.
+ *
+ * 
+ * @version $Revision$
+ * 
+ ****  C A N A D I A N   A S T R O N O M Y   D A T A   C E N T R E  *****
+ ************************************************************************
+ */
+ 
+ package ca.nrc.cadc.ac.admin;
+
+/**
+ * Exception thrown when a problem with the command line arguments is
+ * encountered.
+ */
+public class UsageException extends Exception
+{
+    private static final long serialVersionUID = -661234412216725414L;
+
+    public UsageException(String message)
+    {
+        super(message);
+    }
+}
diff --git a/projects/cadcAccessControl-Admin/src/userAdmin.mf b/projects/cadcAccessControl-Admin/src/userAdmin.mf
new file mode 100644
index 00000000..904fb82f
--- /dev/null
+++ b/projects/cadcAccessControl-Admin/src/userAdmin.mf
@@ -0,0 +1 @@
+Main-Class: ca.nrc.cadc.ac.admin.Main
-- 
GitLab