Skip to content

Conversation

@Bubballoo3
Copy link
Contributor

@Bubballoo3 Bubballoo3 commented Oct 30, 2025

Contributes to #4121. I ran into an error with the collaborative projects where a project can be created by one user, imported by another, but not opened by the non-owning user. The cause was that some directories under .ondemand/ were only created upon the first use, which was the call to ProjectsController#show. So if the owner creates a project but never opens it, these directories are not created, and when the other user opens it, they do not have the permission to create them.

This solves the issue by ensuring that all the necessary directories are created along with the project, so that we have an absolute guarantee that they are always created by the project owner. This allows a non-owning collaborator to be the first one to open a project without errors.

There is also the possibility that I have configured the project root incorrectly. The collaborating user currently has read and execute access to the project root, but not write access. As far as I understand this is what we expect shared projects to be created with, but open to correction if I am mistaken

Comment on lines 305 to 306
Workflow.workflow_dir(project_dataroot)
JobLogger::JobLoggerHelper.log_file(project_dataroot)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not in love with the fact that you're calling these expressly for the side affects and not the return value.

The log_file especially should fix itself whenever upsert_job! or similar is called.

Can't speak to the workflow_dir but it seems like it should follow the same pattern of mkpath unless <it> exist?

There's got to be a better way here.

Copy link
Contributor Author

@Bubballoo3 Bubballoo3 Oct 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like both of these functions serve the dual role of accessing the correct path and making sure it exists (creating it if necessary)

def workflow_dir(project_dir)
dir = Pathname.new("#{project_dir}/.ondemand/workflows")
FileUtils.mkdir_p(dir) unless dir.exist?
dir
end

def log_file(directory)
Pathname.new("#{directory}/.ondemand/job_log.yml").tap do |path|
FileUtils.touch(path.to_s) unless path.exist?
end
end

and both include the check for existence internally. The real issue is that if these files don't exist when the project is created, then someone else might open the project and lack the permissions to create the files. One other approach could be redirecting you to ProjectController#show after clicking save instead of ProjectsController#index, which would force the creator to be the first one to open it (and both of these methods are called during the show action).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My guess is that the way it's written now just doesn't jive with shareable projects.

Seems to me that when the owner creates the project - we just initialize all required directories & files. The way this was originally written (likely by me 😆) doesn't account for/work well for this use case so we likely should refactor it to have better/cleaner initialization.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I think that was what I was trying to achieve with these changes. Those methods seemed to be the source of truth on the paths, so I didn't want to define them again in a separate place. Though with these changes the project creation initializes these paths, what other refactoring did you have in mind? Or do you mean moving those methods to the Project class?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We talked about this in person - but to keep the reference here I mean refactoring so that these methods don't have side affects. That is they can return a Pathname as they always have, but they shouldn't also create the path if it doesn't exist.

@Bubballoo3
Copy link
Contributor Author

The refactor has been done, but there are a few places in the tests where we need to expect the changes in behavior

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

Projects

Status: Awaiting Review

Development

Successfully merging this pull request may close these issues.

4 participants