transaccion en funcion...
Titulo tentador ese para entrar y decirle no se puede... pero bue'
Estoy trabajando en un pequeño framework que se basa mucho en SQL, hace ya un mes estoy luchando en el como hacer la sesiones, pense en Radios, PAS, LDAP, etc, pero nada me sirve... creo, termine por modificar un modulo de apache para que haga lo q necesito
En forma gráfica para q se den una idea:
Usuario <-> HTTPD <-> APACHE_MOD_MYSQL <-> MYSQL
|
+-> Permite acceso <-> Recurso
|
Deniega Acceso
Y ahora los taladro con un esquema de la idea:
/*recurso*/
DROP TABLE IF EXISTS `resource`; /* supongamos una página le asigno un id*/
CREATE TABLE `resource`(
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
`name` VARCHAR(50) /*doesn't matter*/
);
DROP TABLE IF EXISTS `alloworrestrict`;
/*permitir o restringir*/
CREATE TABLE `alloworrestrict`(/*con el id del recurso, id del usuario y una clave con lo q hacer */
resource_id INT,
user_id INT,
`lock` ENUM('ALLOW','RESTRICT')
);
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`(/*la tabla de usuario comun*/
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50),
pass VARCHAR(50)
);
DROP TABLE IF EXISTS `session`;
CREATE TABLE session(/*las bendita sessiones, relacionada con el usuario y un hash*/
user_id INT,
hash VARCHAR(32)
) ENGINE=innoDB;
INSERT INTO resource(name) VALUES('first');
INSERT INTO resource(name) VALUES('second');
INSERT INTO user(name,pass) VALUES('john','123');
/*lo anterior cargamos datos, aquí le bloqueamos a john el recurso con id 2*/
INSERT INTO alloworrestrict(resource_id,user_id,`lock`) VALUES(2,1,'RESTRICT');
/*funcion para crear una sesion*/
DELIMITER $$ ;
CREATE FUNCTION create_session(id INT)
RETURNS VARCHAR(32)
READS SQL DATA
BEGIN
DECLARE `loop` INT DEFAULT 1;
DECLARE `THASH` VARCHAR(32) NOT NULL DEFAULT '';
/*todo esto crea una session, por favor notar q esta mal porque no puede haber transacciones es a modo de ejemplo*/
SET AUTOCOMMIT=0;
START TRANSACTION;
WHILE loop > 0 DO
SET THASH = MD5(RAND(9999999999999999999)*999999999999999999);
IF NOT (SELECT `hash` FROM `session` WHERE `hash`=THASH LIMIT 1) THEN
INSERT INTO session(user_id,hash) VALUES(id,THASH);
SET `loop` = 0;
END IF;
END WHILE;
COMMIT;
RETURN THASH;
END $$
DELIMITER ; $$
/*hacemos como si navegamos, el usuario se valida*/
SET @tuid = SELECT id FROM `user` WHERE name='John' AND pass='123' LIMIT 1;
/* validado creamos la sesion*/
SET @hash = SELECT create_session(@tuid);
/*la sesion la enviamos en una cookie y la captura el modulo de apache, todo lo de abajo en realidad va en una funcion tambien pero no compliquemos*/
SET @uid = SELECT IFNULL(id,0) FROM session WHERE hash=@hash LIMIT 1;
/*chequemos si el recurso esta bloqueado para él o para alguien*/
IF @uid THEN
/*si hay sesion habrá @uid sino no, en este caso chequeamos que el recurso no este bloqueado para este especifico usuario*/
SET @rac = SELECT IFNULL(`lock`,'') FROM alloworrestrict WHERE resource=2 AND user_id = @uid LIMIT 1;
ELSE
/*no habiendo @uid chequeamo si hay alguien que fué bloqueado en ese caso denegamos tambien*/
SET @rac = SELECT IFNULL(`lock`,'') FROM alloworrestrict WHERE resource=2 LIMIT 1;
END IF;
/*hacemos la comprobación y resultado de lo anterios, si esta validado y no esta bloqueado lo mostramos*/
IF (@uid AND @rac <> 'RESTRICT') THEN
SELECT 'ACCESS';
/*si no esta registrado pero no hay bloqueo de recurso lo mostramos*/
ELSE IF (@uid =0 AND @rac <> 'RESTRICT') THEN
SELECT 'ACCESS';
ELSE
/*si no se da ninguna de las condiciones anteriores no mostramos nada*/
SELECT 'DENIED';
END IF;
/*el modulo de apache espera estas respuesta para saber que hacer*/
Más o menos es la idea, se que no se puede utilizar transaciones en funciones, pero probé las transacciones progresivas y tampoco funca, recibí este error ERROR 1400 (XAE09): XAER_OUTSIDE: Some work is done outside global transaction when execute the function.
Que puedo hacer que se les ocurre, como lo han implementado ustedes?
Esto es por si quieren probar las transciones progresiva q no funca.
DROP TABLE IF EXISTS `se`;
CREATE TABLE `se`(
`id`INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
`name` VARCHAR(25)
) ENGINE=innoDB;
DROP FUNCTION IF EXISTS `ses`;
DELIMITER $$ ;
CREATE FUNCTION `ses`()
RETURNS INT(11)
READS SQL DATA
BEGIN
XA START 'XAsession';
INSERT INTO `se`(`name`) VALUES ('john');
SET @tmp_password = LAST_INSERT_ID();
XA END 'XAsession';
XA PREPARE 'XAsession';
XA COMMIT 'XAsession';
RETURN @tmp_password;
END $$
DELIMITER ; $$
/*no funciona*/
SELECT ses();
/*funciona*/
XA START 'XAsession';
INSERT INTO `se`(`name`) VALUES ('john');
SET @tmp_password = LAST_INSERT_ID();
XA END 'XAsession';
XA PREPARE 'XAsession';
XA COMMIT 'XAsession';
SELECT @tmp_password;
Comentarios, sugerencia, ayuda, ejemplos, puteadas, alabanzas, delirio ha estas altura me parece q todo es bienvenido :-D.
Bueno si leyeron hasta acá se merecen un gran saludos!!!!
Martín
PD: sorry las partes q estan en mal ingles, pero lo había posteado en otro lado hace un tiempo y naranja.