[Feature]: `createTaskFile`/`createProjectFile` cannot set the uploader: Add optional `creator_id`
Feature Summary
Add an optional creator_id parameter to createTaskFile and createProjectFile, validated the same way createTask already validates owner_id/creator_id.
What problem does this feature solve?
FileModel::create() always sets user_id from $this->userSession->getId() ?: 0. Via the Application API (global token) there's no session, so uploaded files get user_id = 0 and show no "Uploaded by" attribution in the UI — unlike files uploaded through the web UI. There's no parameter anywhere in createTaskFile → uploadContent → create to override this.
Originally reported in #2645 (2016), closed with no resolution. Still true in 1.2.54.
Use case
We have a bridge service running, that imports (creates/updates) cards from another system. It would be nice being able to mark attachments as belonging to an user – just like we already do for the tasks themselves.
Proposed Solution
Precedent
createTask solves the identical problem for owner_id/creator_id:
if ($owner_id !== 0 && ! $this->projectPermissionModel->isAssignable($project_id, $owner_id)) {
return false;
}and
if ($creator_id !== 0 && ! $this->projectPermissionModel->isAssignable($project_id, $creator_id)) {
return false;
}Both validated against project membership via isAssignable(), no session special-casing. Introduced by commit f8c9ebd672efe19aa407793bb5b12965564df31f, "fix(api): allow and validate creator ID assignment in task creation" (direct commit to app/Api/Procedure/TaskProcedure.php, no associated PR found).
Proposed patches
Attached: a 6-commit series against kanboard/kanboard plus 1 commit against kanboard/documentation. Applied via git am to a fresh v1.2.54 clone and verified against a live instance (Apache + mod_php + sqlite, matching .github/workflows/integration_tests.yml):
FileModel::create(): optional$creator_idparam, falls back to current behavior when0.FileModel::uploadContent(): pass the parameter through.TaskFileProcedure::createTaskFile(): acceptscreator_id, validated viaprojectPermissionModel->isAssignable(), identical tocreateTask. An invalid ID is logged server-side and thrown to the client asJsonRPC\Exception\ResponseException(code 422, withcreator_id/project_idin getData()) rather than a barefalse. The error code was chosen deliberately over the JSON-RPC-reserved-32602, since the reference client'sResponseParserspecial-cases-32602into a genericInvalidArgumentExceptionand silently drops the data field.ProjectFileProcedure::createProjectFile(): dito (parity)- Unit tests covering explicit
creator_idonFileModel::create()/uploadContent(). - Integration tests covering both the accepted and rejected
creator_idcases via the live API, following the existing assignability-test style inSubtaskProcedureTest.php. - (docs repo) Document the new parameter.
The error response was made more descriptive on purpose. Today an API client has basically no way to tell error classes/reasons apart, since false is the only real error signal. With the added code here, I didn't want to continue that pattern and actually tell the API client, where things fell apart. If you prefer a plain false, please let me know and I can change that.
If you want PRs over the patches attached here, let me know and I'll open them.
Note: Anthropic's Sonnet 5 model was used to formulate the patches, since I didn't have time to dig through the Kanboard code base in detail. If you want a "pure human" implementation, I'd out here an can just provide the ticket itself then. I don't have real time available for this relatively minor issue.
Alternatives Considered
There are no alternatives, if you want to have the attribution for files. At least none that I can see.
Additional Context
No response
Checklist
- I have searched existing issues to ensure this feature hasn't been requested before.
- I understand that feature requests are not guaranteed to be implemented.
Source: kanboard/kanboard