MerginMaps / MerginMaps/server
Newly created project gets no project_member row — creator holds no role, sharing is impossible
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 179
- Forks
- 71
- Avg merge
- 1d 4h
- Merged PRs (30d)
- 10
Description
Summary
add_project() never grants the creator a role on the new project. No row is written to
project_member at all, so the project ends up with no roles whatsoever.
Consequences:
- Sharing is broken. With no roles on the project, the web UI's Collaborators page cannot add
anyone — including the owner adding themselves. This was the presenting symptom for us. - With
GLOBAL_ADMIN=True, the creator cannot see their own project.
Environment
| Image | lutraconsulting/merginmaps-backend:2025.7.3 (self-reports 2025.6.2, see #548) |
| Deployment | self-hosted CE, Docker Compose, single global workspace |
| Config | GLOBAL_READ / GLOBAL_WRITE / GLOBAL_ADMIN all unset (default False) |
Verified still present in the current source — add_project() is structurally unchanged at
2025.7.3, 2025.8.0, 2025.8.1, 2025.8.2, 2026.4.2, 2026.5.0, 2026.6.0 and 2026.6.2.
None of them calls set_role.
Steps to reproduce
- Create a project — web UI or
POST /v1/project/{namespace}; both reproduce it. - Query the database:
SELECT p.name, u.username, pm.role
FROM project p
LEFT JOIN project_member pm ON pm.project_id = p.id
LEFT JOIN "user" u ON u.id = pm.user_id
WHERE p.name = '<new project>';
Expected: the creator holds owner.
Actual: no rows.
Observed on two projects created by two different users through two different paths:
schema-change-test | (NO MEMBERS) <- created in the web UI by a superuser
list-refresh-test | (NO MEMBERS) <- created via the REST API by a non-superuser
Two older projects on the same server do have admin:owner rows — they were migrated in from
another host with their rows already present, which is why this went unnoticed at first.
Why the creator loses visibility
GlobalWorkspaceHandler.get_user_role() returns OWNER for is_admin users and GUEST for
everyone else when the GLOBAL_* settings are at their defaults. A GUEST reaches a project only
via project_member or Project.public — so a non-superuser who creates a project immediately
cannot see it.
Reproduced with a non-superuser that had been granted create rights:
GET /v1/project/paginated?flag=created -> count=0
flag=created filters on Project.creator_id == user.id and the user is the creator, but
projects_query(ProjectPermissions.Read) discards the project before the creator test is reached.
Cause
server/mergin/sync/public_api_controller.py, add_project() builds the project with
creator=current_user, adds a ProjectVersion, and commits — but never calls set_role.
Project.__init__ (sync/models.py) sets self.creator and does not call it either. The only
callers of set_role are the explicit collaborator endpoints in public_api_v2_controller.py.
Suggested fix
In add_project(), before db.session.commit():
p.set_role(current_user.id, ProjectRole.OWNER)
A data migration granting owner to creator_id for existing projects that have no
project_member rows would repair servers already affected.
I'm happy to open a PR for this if it would be useful.
Workaround
INSERT INTO project_member (project_id, user_id, role)
SELECT p.id, u.id, 'owner'::project_role
FROM project p JOIN "user" u ON u.username = '<owner>'
WHERE p.name = '<project>'
ON CONFLICT DO NOTHING;
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in server/mergin/sync/public_api_controller.py at add_project(), then inspect Project.init in sync/models.py and the set_role callers in public_api_v2_controller.py. Exercise POST /v1/project/{namespace} and verify a newly created project has an owner project_member row and remains visible to its creator; consider the stated migration separately for existing projects without members.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python, sql
- Domain
- api, authorization, backend, database
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 78/100