Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

File Mode / Permissions Interface #49

Open
tristanlins opened this issue Dec 14, 2012 · 1 comment
Open

File Mode / Permissions Interface #49

tristanlins opened this issue Dec 14, 2012 · 1 comment

Comments

@tristanlins
Copy link
Member

Currently we do not work around different permission systems.
How about to introduce an interface and some classes to handle this problem.

interface FileMode // or FilePermissions
{
    const TYPE = 'unknown';

    /**
     * Check if file modes are supported by the fs.
     *
     * @return bool
     */
    public function isSupported();

    /**
     * Test if file is readable for the current user.
     * Which "user" is referenced, depends on the implementation
     * and have to be automatically detected.
     *
     * @return bool
     */
    public function isReadable();

    /**
     * Test if file is writeable for the current user.
     * Which "user" is referenced, depends on the implementation
     * and have to be automatically detected.
     *
     * @return bool
     */
    public function isWriteable();

    /**
     * Test if file is executeable for the current user.
     * Which "user" is referenced, depends on the implementation
     * and have to be automatically detected.
     *
     * @return bool
     */
    public function isExecuteable();

    /**
     * For stacked file permission systems, get the next hop.
     *
     * @return FileMode
     */
    public function nextFileMode();
}

Then we have multiple classes with specific methods.
The UnsupportedFileMode class that indicate that file permissions are not supported.

class UnsupportedFileMode implements FileMode
{
    const TYPE = 'unsupported';

    public function isSupported()
    {
        return false;
    }
}

The PrimitiveFileMode only know read, write, executeable. It does not know owner, groups or complex acl rules.

class PrimitiveFileMode implements FileMode
{
    const TYPE = 'primitive';

    public function isSupported()
    {
        return true;
    }
    public function isReadable();
    public function isWriteable();
    public function isExecuteable();
}

The UnixFileMode only know read, write, executeable for owner, groups and others.

class UnixFileMode implements FileMode
{
    const TYPE = 'unix';

    public function isSupported()
    {
        return true;
    }
    public function isOwnerReadable();
    public function isOwnerWriteable();
    public function isOwnerExecuteable();
    public function isGroupReadable();
    public function isGroupWriteable();
    public function isGroupExecuteable();
    public function isOthersReadable();
    public function isOthersWriteable();
    public function isOthersExecuteable();
    public function isSticky();
    // maybe more
}

As you expected, the ACLFileMode will allow access to acl rules.

An interface system like this allow us to respect the different permission system.
The FileMode::isSupported is mandatory, because in mounted or merged filesystem I don't have access to the underlaying filesystem to check the "file permissions" ability. The UnsupportedFileMode prevents File::getMode from returning null.

Also other systems are allowed to implement there own permission system. For example Contao could implement it's own ContaoPermissionsFileMode for example.

class ContaoPermissionsFileMode implements FileMode
{
    const TYPE = 'contao';

    public function isSupported()
    {
        return true;
    }
    public function isUserReadable($backendUserId);
    public function isUserWriteable($backendUserId);
    public function isMemberReadable($memberId);
    public function isMemberWriteable($memberId);
}

To allow access to different permission systems, for example the ContaoPermissionsFileMode is just an overlay over UnixFileMode, the File::getMode should be extended with a type parameter:

interface File
{
    /**
     * Get permission access object for this file.
     *
     * @param string $type The permission system to access.
     * If null the filesystem default permission system will be returned.
     *
     * @throw UnsupportedPermissionSystemException will be thrown if the requested permission system is not available.
     */
    public function getMode($type = null);
}

To access different permission systems just use the TYPE constant:

/** @var ContaoFilesystem $fs */
$file = $fs->getFile('foo');

/** @var ContaoPermissionsFileMode $contaoPerms */
$contaoPerms = $file->getMode();

// forcing a permission system (not good)
try {
    /** @var UnixFileMode $unixPerms */
    $unixPerms = $file->getMode(UnixFileMode::TYPE);
} catch (UnsupportedPermissionSystemException $e) {
    // unix unsupported, maybe it is a linked in remote share like dropbox or amazon S3
}

// get the next permission system (good way)
/** @var UnixFileMode|DropboxFileMode|AmazonS3FileMode|... $nextPerms */
$nextPerms = $contaoPerms->nextFileMode();

This allow us to transparent add file permission systems, nobody knows about it, but it will protect the files. The File::isReadable, File::isWriteable and File::isExecuteable should be shortcuts to the FileMode::isReadable, FileMode::isWriteable, FileMode::isExecuteable methods.

@tristanlins
Copy link
Member Author

The method

    /**
     * For stacked file permission systems, get the next hop.
     *
     * @return FileMode
     */
    public function nextFileMode();

will be dropped. The adapter have to check its own native permissions and then check permission - if available - against an extended permission manager.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant