/*----- PROTECTED REGION ID(TangoAccessControl.h) ENABLED START -----*/
//=============================================================================
//
// file :        TangoAccessControl.h
//
// description : Include for the TangoAccessControl class.
//
// project :     Tango Access Control Management.
//
//
// Copyright (C) :      2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014
//						European Synchrotron Radiation Facility
//                      BP 220, Grenoble 38043
//                      FRANCE
//
// This file is part of Tango.
//
// Tango is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// Tango is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with Tango.  If not, see <http://www.gnu.org/licenses/>.
//
//
// $Author$
//
// $Revision$
// $Date$
//
//=============================================================================
//                This file is generated by POGO
//        (Program Obviously used to Generate tango Object)
//=============================================================================


#ifndef TANGOACCESSCONTROL_H
#define TANGOACCESSCONTROL_H


#include <tango/tango.h>
#include "AccessControl.h"
#include <mysql.h>

#ifndef LIBMARIADB
#if MYSQL_VERSION_ID >= 80001
typedef bool my_bool;
#endif
#endif

#define	CONTROL_SYSTEM				"CtrlSystem"
#define SERVICE_PROP_NAME			"Services"
#define ServiceName					"AccessControl"
#define InatanceName				"tango"
 
#define AC_SQLError 				"AC_SQLError"
#define AC_IncorrectArguments		"AC_IncorrectArguments"
#define AC_AlreadyExists			"AC_AlreadyExists"

#define	STARTER_DEVNAME_HEADER	"tango/admin/"

typedef struct {
	std::string	user;
	std::string	device;
	std::string	address;
	std::string	rights;
}
AccessStruct;

//	Define time measuremnt type (depends on OS)
#ifndef WIN32

#	define	TimeVal	struct timeval
#	define	GetTime(t)	gettimeofday(&t, NULL);
#	define	Elapsed(before, after)	\
		1000.0*(after.tv_sec-before.tv_sec) + \
		((double)after.tv_usec-before.tv_usec) / 1000

#else

static LARGE_INTEGER	cpu_freq;
#	define	TimeVal	LARGE_INTEGER
#	define	GetTime(t)	w_gettimeofday(&t);
#	define	Elapsed(before, after)		\
		(cpu_freq.QuadPart==0) ? 0.0 :	\
			(double) (after.QuadPart - before.QuadPart)/cpu_freq.QuadPart * 1000;

#endif	/*	WIN32		*/


/*----- PROTECTED REGION END -----*/	//	TangoAccessControl.h

/**
 *  TangoAccessControl class description:
 *    This class is a conceate class inherited from AccessControl abstract class.<Br>
 *    <Br>
 *    This class defines how to manage the TANGO access control.<Br>
 *    It implements commands for tool to defines access for users, devices and IP addresses.<Br>
 *    It implements also commands used by client API to check access for specified user, device and address.<Br>
 *    And it implements register and unregister it as TANGO service.
 */

namespace TangoAccessControl_ns
{
/*----- PROTECTED REGION ID(TangoAccessControl::Additional Class Declarations) ENABLED START -----*/

		//		Additional Class Declarations
class DummyDev: public Tango::Connection
{
public:
	DummyDev():Tango::Connection(true) {};

	virtual std::string get_corba_name(bool) {std::string str;return str;}
	virtual std::string build_corba_name() {std::string str;return str;}
	virtual int get_lock_ctr() {return 0;}
	virtual void set_lock_ctr(int) {};

	virtual std::string dev_name() {std::string str;return str;}

	int get_env_var(const char *cc,std::string &str_ref) {return Tango::Connection::get_env_var(cc,str_ref);}
};

	/*----- PROTECTED REGION END -----*/	//	TangoAccessControl::Additional Class Declarations

class TangoAccessControl : public AccessControl_ns::AccessControl
{

/*----- PROTECTED REGION ID(TangoAccessControl::Data Members) ENABLED START -----*/

	//		Add your own data members
public:



	/*----- PROTECTED REGION END -----*/	//	TangoAccessControl::Data Members



//	Constructors and destructors
public:
	/**
	 * Constructs a newly device object.
	 *
	 *	@param cl	Class.
	 *	@param s 	Device Name
	 */
	TangoAccessControl(Tango::DeviceClass *cl,std::string &s);
	/**
	 * Constructs a newly device object.
	 *
	 *	@param cl	Class.
	 *	@param s 	Device Name
	 */
	TangoAccessControl(Tango::DeviceClass *cl,const char *s);
	/**
	 * Constructs a newly device object.
	 *
	 *	@param cl	Class.
	 *	@param s 	Device name
	 *	@param d	Device description.
	 */
	TangoAccessControl(Tango::DeviceClass *cl,const char *s,const char *d);
	/**
	 * The device object destructor.
	 */
	~TangoAccessControl() {delete_device();};


//	Miscellaneous methods
public:
	/*
	 *	will be called at device destruction or at init command.
	 */
	void delete_device();
	/*
	 *	Initialize the device
	 */
	virtual void init_device();
	/*
	 *	Always executed method before execution command method.
	 */
	virtual void always_executed_hook();


//	Attribute methods
public:
	//--------------------------------------------------------
	/*
	 *	Method      : TangoAccessControl::read_attr_hardware()
	 *	Description : Hardware acquisition for attributes.
	 */
	//--------------------------------------------------------
	virtual void read_attr_hardware(std::vector<long> &attr_list);


	//--------------------------------------------------------
	/**
	 *	Method      : TangoAccessControl::add_dynamic_attributes()
	 *	Description : Add dynamic attributes if any.
	 */
	//--------------------------------------------------------
	void add_dynamic_attributes();




//	Command related methods
public:
	/**
	 *	Command AddAddressForUser related method
	 *	Description: Add an address for the specified user..
	 *
	 *	@param argin user name, address
	 */
	virtual void add_address_for_user(const Tango::DevVarStringArray *argin);
	virtual bool is_AddAddressForUser_allowed(const CORBA::Any &any);
	/**
	 *	Command AddDeviceForUser related method
	 *	Description: Add a device and rights for the specified user..
	 *
	 *	@param argin user name, device adn value
	 */
	virtual void add_device_for_user(const Tango::DevVarStringArray *argin);
	virtual bool is_AddDeviceForUser_allowed(const CORBA::Any &any);
	/**
	 *	Command CloneUser related method
	 *	Description: Copy addresses and devices from source user to target user.
	 *
	 *	@param argin [0] - source user name.\n[1] - target user name.
	 */
	virtual void clone_user(const Tango::DevVarStringArray *argin);
	virtual bool is_CloneUser_allowed(const CORBA::Any &any);
	/**
	 *	Command GetAccess related method
	 *	Description: Check access for specified user, device, address
	 *                    and returns access (read or write).
	 *
	 *	@param argin [0] - User name
	 *               [1] - IP Address
	 *               [2] - Device
	 *	@returns access for specified inputs  read/write.
	 */
	virtual Tango::DevString get_access(const Tango::DevVarStringArray *argin);
	virtual bool is_GetAccess_allowed(const CORBA::Any &any);
	/**
	 *	Command GetAccessForMultiIP related method
	 *	Description: Check access for specified user, device and addresses
	 *                    and returns access (read or write).
	 *
	 *	@param argin [0] - User name
	 *               [1] - Device
	 *               [2] - IP Address #1
	 *               [3] - IP Address #2
	 *               [4] - IP Address #3
	 *               [5] - IP Address #4
	 *               ......
	 *	@returns access for specified inputs  read/write.
	 */
	virtual Tango::DevString get_access_for_multi_ip(const Tango::DevVarStringArray *argin);
	virtual bool is_GetAccessForMultiIP_allowed(const CORBA::Any &any);
	/**
	 *	Command GetAddressByUser related method
	 *	Description: Returns address list  found for the specified user.
	 *
	 *	@param argin user name.
	 *	@returns Addresses found for the specified user.
	 */
	virtual Tango::DevVarStringArray *get_address_by_user(Tango::DevString argin);
	virtual bool is_GetAddressByUser_allowed(const CORBA::Any &any);
	/**
	 *	Command GetAllowedCommandClassList related method
	 *	Description: Returns the class names which have AllowedAccessCmd property defined.
	 *
	 *	@returns Class names which have AllowedAccessCmd property defined.
	 */
	virtual Tango::DevVarStringArray *get_allowed_command_class_list();
	virtual bool is_GetAllowedCommandClassList_allowed(const CORBA::Any &any);
	/**
	 *	Command GetAllowedCommands related method
	 *	Description: Returns allowed command list found in database for specified device
	 *               It search the class of the specified device and then uses the class property <b>AllowedAccessCmd</b>
	 *
	 *	@param argin Device name OR Device Class name
	 *	@returns Allowed commands found in database for specified device
	 */
	virtual Tango::DevVarStringArray *get_allowed_commands(Tango::DevString argin);
	virtual bool is_GetAllowedCommands_allowed(const CORBA::Any &any);
	/**
	 *	Command GetDeviceByUser related method
	 *	Description: Returns devices and rights found for the specified user.
	 *
	 *	@param argin user name.
	 *	@returns devices and rights found for the specified user.
	 */
	virtual Tango::DevVarStringArray *get_device_by_user(Tango::DevString argin);
	virtual bool is_GetDeviceByUser_allowed(const CORBA::Any &any);
	/**
	 *	Command GetDeviceClass related method
	 *	Description: Returns class for specified device.
	 *
	 *	@param argin Device name
	 *	@returns Class found in database for specified device
	 */
	virtual Tango::DevString get_device_class(Tango::DevString argin);
	virtual bool is_GetDeviceClass_allowed(const CORBA::Any &any);
	/**
	 *	Command GetUsers related method
	 *	Description: Returns user list found in table access_address.
	 *
	 *	@returns Users find in table access_address.
	 */
	virtual Tango::DevVarStringArray *get_users();
	virtual bool is_GetUsers_allowed(const CORBA::Any &any);
	/**
	 *	Command RegisterService related method
	 *	Description: Register device as a TANGO service.
	 *
	 */
	virtual void register_service();
	virtual bool is_RegisterService_allowed(const CORBA::Any &any);
	/**
	 *	Command RemoveAddressForUser related method
	 *	Description: Remove an address for the specified user..
	 *
	 *	@param argin user name, address
	 */
	virtual void remove_address_for_user(const Tango::DevVarStringArray *argin);
	virtual bool is_RemoveAddressForUser_allowed(const CORBA::Any &any);
	/**
	 *	Command RemoveDeviceForUser related method
	 *	Description: Remove a device and its rights for the specified user..
	 *
	 *	@param argin user name, device and value
	 */
	virtual void remove_device_for_user(const Tango::DevVarStringArray *argin);
	virtual bool is_RemoveDeviceForUser_allowed(const CORBA::Any &any);
	/**
	 *	Command RemoveUser related method
	 *	Description: Remove all records for specified user.
	 *
	 *	@param argin user name
	 */
	virtual void remove_user(Tango::DevString argin);
	virtual bool is_RemoveUser_allowed(const CORBA::Any &any);
	/**
	 *	Command UnregisterService related method
	 *	Description: Unregister device as a TANGO service.
	 *
	 */
	virtual void unregister_service();
	virtual bool is_UnregisterService_allowed(const CORBA::Any &any);


	//--------------------------------------------------------
	/**
	 *	Method      : TangoAccessControl::add_dynamic_commands()
	 *	Description : Add dynamic commands if any.
	 */
	//--------------------------------------------------------
	void add_dynamic_commands();

/*----- PROTECTED REGION ID(TangoAccessControl::Additional Method prototypes) ENABLED START -----*/

	//	Additional Method prototypes
protected :	
	MYSQL mysql;

	std::string         removeFQDN(std::string s);
	void           mysql_connection();
	void           simple_query(std::string sql_query,const char *method);
	MYSQL_RES     *query(std::string sql_query,const char *method);
	std::vector<std::string> get_dev_members(std::string &devname);
	std::vector<std::string> get_ip_add_members(std::string &devname);

	std::vector<AccessStruct>
		get_access_for_user_address(std::string &user, std::string &ip_add);
	std::string get_access_for_user_device(std::string &user, std::string &device);
	std::string get_rigths(std::vector<AccessStruct> as, std::vector<std::string> members);
	bool match(std::string expression, std::string member);

	void register_service(std::string servicename, std::string instname, std::string devname);
	void unregister_service(std::string servicename, std::string instname, std::string devname);

	/*----- PROTECTED REGION END -----*/	//	TangoAccessControl::Additional Method prototypes
};

/*----- PROTECTED REGION ID(TangoAccessControl::Additional Classes Definitions) ENABLED START -----*/

	//	Additional Classes definitions

	/*----- PROTECTED REGION END -----*/	//	TangoAccessControl::Additional Classes Definitions

}	//	End of namespace

#endif   //	TangoAccessControl_H
