我是mySQL的新手,我甚至不知道从哪里开始。我想知道如何编写一个简单的函数,它根据分布在许多表中的值返回true或false。
以下是我的表的相关部分(所有引擎都是innodb
)。在您阅读时,您将看到数据库只是为这些用户/组存储用户,组,文件以及这些文件的权限。
USER表:
CREATE TABLE IF NOT EXISTS USER
(
ID INT NOT NULL auto_increment,
PRIMARY KEY(ID)
)
GROUP表:
CREATE TABLE IF NOT EXISTS GROUP
(
ID INT NOT NULL AUTO_INCREMENT,
PRIMARY KEY(ID)
)
GROUP MEMBERSHIP表:
CREATE TABLE IF NOT EXISTS GROUPMEMBERSHIP
(
ID INT NOT NULL AUTO_INCREMENT,
USERID INT NOT NULL,
GROUPID INT NOT NULL,
UNIQUE ( USERID, GROUPID ),
PRIMARY KEY(ID),
FOREIGN KEY (USERID) REFERENCES USER(ID),
FOREIGN KEY (GROUPID) REFERENCES GROUP(ID)
)
文件表:(R,W,X,适用于other
)
CREATE TABLE IF NOT EXISTS FILE
(
ID INT NOT NULL AUTO_INCREMENT,
READ BOOLEAN DEFAULT FALSE,
WRITE BOOLEAN DEFAULT FALSE,
EXECUTE BOOLEAN DEFAULT FALSE,
PRIMARY KEY(ID)
)
FILE USER PERMISSIONS表:
CREATE TABLE IF NOT EXISTS FILEUSERPERMISSIONS
(
ID INT NOT NULL AUTO_INCREMENT,
FILEID INT NOT NULL,
USERID INT NOT NULL,
READ BOOLEAN DEFAULT FALSE,
WRITE BOOLEAN DEFAULT FALSE,
EXECUTE BOOLEAN DEFAULT FALSE,
UNIQUE (FILEID, USERID),
PRIMARY KEY(ID),
FOREIGN KEY (FILEID) REFERENCES FILE(ID),
FOREIGN KEY (USERID) REFERENCES USER(ID)
)
文件组权限表:
CREATE TABLE IF NOT EXISTS FILEGROUPPERMISSIONS
(
ID INT NOT NULL AUTO_INCREMENT,
FILEID INT NOT NULL,
GROUPID INT NOT NULL,
READ BOOLEAN DEFAULT FALSE,
WRITE BOOLEAN DEFAULT FALSE,
EXECUTE BOOLEAN DEFAULT FALSE,
UNIQUE (FILEID, GROUPID),
PRIMARY KEY(ID),
FOREIGN KEY (FILEID) REFERENCES FILE(ID),
FOREIGN KEY (GROUPID) REFERENCES GROUP(ID)
)
hasPermission功能:
DELIMITER $$
DROP FUNCTION IF EXISTS hasPermission$$
CREATE FUNCTION hasPermission(fileID INT, userID INT)
RETURNS BOOLEAN
BEGIN
???
END$$
DELIMITER ;
我将如何进行,或者至少在哪里开始编写hasPermission
函数,以便在查询时如此:
SELECT hasPermission( 123, 456)
执行以下内容:
other
第一个是非常琐碎的三者中最微不足道的。第二个让我难过。第三个对我来说是一个概念障碍。除此之外,我显然必须检查用户和/或文件是否存在。
请善待,因为我是MySQL的新手。
先谢谢你
答案 0 :(得分:2)
检查文件123是否可由other
你说这是微不足道的,但为了完整性:
SELECT READ
FROM FILE
WHERE ID = 123;
检查用户456是否具有文件123的读取权限
您可以使用FILEUSERPERMISSIONS
表中的类似查找来执行此操作:
SELECT READ
FROM FILEUSERPERMISSIONS
WHERE FILEID = 123 AND USERID = 456;
检查用户456是否在某个具有文件123读取权限的组中
要完成此操作,您需要JOIN GROUP MEMBERSHIP
和FILE GROUP PERMISSIONS
表:
SELECT READ
FROM FILEGROUPPERMISSIONS JOIN GROUPMEMBERSHIP USING (GROUPID)
WHERE FILEID = 123 AND USERID = 456;
要将这些组合在一起,您可以这样做:
SELECT
(SELECT READ FROM FILE WHERE ID = 123)
OR (SELECT READ FROM FILEUSERPERMISSIONS WHERE FILEID = 123 AND USERID = 456)
OR (SELECT READ FROM FILEGROUPPERMISSIONS JOIN GROUPMEMBERSHIP USING (GROUPID)
WHERE FILEID = 123 AND USERID = 456);
答案 1 :(得分:2)
检查文件的权限。我可能会这样做:
SELECT
(
CASE WHEN EXISTS
(
SELECT
NULL
FROM
FILE
WHERE EXISTS
(
SELECT
NULL
FROM
USER
JOIN GROUPMEMBERSHIP
ON GROUPMEMBERSHIP.USERID=USER.ID
JOIN FILEUSERPERMISSIONS
ON FILEUSERPERMISSIONS.USERID=GROUPMEMBERSHIP.USERID
JOIN FILEGROUPPERMISSIONS
ON FILEGROUPPERMISSIONS.GROUPID=GROUPMEMBERSHIP.GROUPID
WHERE
FILEUSERPERMISSIONS.FILEID=FILE.ID
AND FILEGROUPPERMISSIONS.FILEID=FILE.ID
AND FILEUSERPERMISSIONS.READ=FILE.READ
AND FILEGROUPPERMISSIONS.READ=FILE.READ
AND USER.ID=userID
)
WHERE
FILE.READ=1
AND FILE.ID=fileID
)
THEN CAST(1 AS BIT)
ELSE CAST(0 AS BIT)
END
) AS hasRights
但如果你真的想要重视你的功能。我建议使用表函数,只提供userid
。这样您就可以获得用户有权访问的所有文件。这看起来像这样:
SELECT
ID
FROM
FILE
WHERE EXISTS
(
SELECT
NULL
FROM
USER
JOIN GROUPMEMBERSHIP
ON GROUPMEMBERSHIP.USERID=USER.ID
JOIN FILEUSERPERMISSIONS
ON FILEUSERPERMISSIONS.USERID=GROUPMEMBERSHIP.USERID
JOIN FILEGROUPPERMISSIONS
ON FILEGROUPPERMISSIONS.GROUPID=GROUPMEMBERSHIP.GROUPID
WHERE
FILEUSERPERMISSIONS.FILEID=FILE.ID
AND FILEGROUPPERMISSIONS.FILEID=FILE.ID
AND FILEUSERPERMISSIONS.READ=FILE.READ
AND FILEGROUPPERMISSIONS.READ=FILE.READ
AND USER.ID=userID
)
WHERE
FILE.READ=1
顺便说一下。问题是大坝好。这应该是如何提问的一个例子
答案 2 :(得分:0)
为了完整性,我也发布了解决方案,解决了这个问题。我最初的动机是创建一个函数来查看一个linux用户(即。user1
)是否可以访问另一个linux用户(即。user2
)主文件夹(即user1
是否有读取/home/user2
的权限。然后我会在使用VIEW
函数为每个mysql用户构造user()
时使用此函数(假设mysql用户名和linux用户名是一对一的)。感谢Arion的建议,我现在正在创建一个使用连接的视图。
注意,出于本示例的目的,主文件夹存储在FILE
表中。
USER_VIEW视图:
CREATE VIEW USER_VIEW
AS
SELECT
U.ID
FROM
USERS AS U
LEFT JOIN FILES AS F
ON U.ID = F.USER_ID
LEFT JOIN FILE_USER_PERMISSIONS AS P
ON F.ID = P.FILE_ID
LEFT JOIN USERS AS S
ON P.USER_ID = S.ID
WHERE
(
U.USERNAME = SUBSTR( USER(), 1, POSITION( '@' IN USER() ) - 1 )
)
OR
(
F.R = TRUE
)
OR
(
U.HOME = F.PATH AND P.R = TRUE AND S.USERNAME = SUBSTR( USER(), 1, POSITION( '@' IN USER() ) - 1 )
)
UNION
SELECT
U.ID
FROM
USERS AS U
LEFT JOIN FILES AS F
ON U.ID = F.USER_ID
LEFT JOIN FILE_GROUP_PERMISSIONS AS P
ON F.ID = P.FILE_ID
LEFT JOIN GROUP_MEMBERSHIP AS G
ON P.GROUP_ID = G.ID
LEFT JOIN USERS AS S
ON G.USER_ID = S.ID
WHERE
(
U.HOME = F.PATH AND P.R = TRUE AND S.USERNAME = SUBSTR( USER(), 1, POSITION( '@' IN USER() ) - 1 )
)
编辑:我相信而不是发出像
这样的命令CREATE VIEW USER_VIEW
AS
SELECT
U.ID
FROM
...
我可以做到
CREATE VIEW USER_VIEW
AS
SELECT
U.*
FROM
...
如果你想要复制10+列
,这会派上用场