fix: migration for basic user

This commit is contained in:
Nikolai Giman
2026-04-19 21:28:55 +02:00
parent 32a2819ebf
commit 7ced0a54e1
9 changed files with 75 additions and 5 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "taskview-ce-api-server",
"version": "1.42.3",
"version": "1.42.5",
"scripts": {
"dev": "bun run --watch ./server.ts",
"start": "NODE_ENV=production node ./dist/taskview-server.js",
+11
View File
@@ -461,5 +461,16 @@
"Added SAML logout URL for SLO",
"Added SCIM provisioning support"
]
},
"37": {
"version": "1.44.0",
"name": "Release 1.44.0",
"releaseDate": "20260418",
"scripts": [
"/1.44.0/0.create-missing-personal-orgs.sql"
],
"description": [
"Create personal organizations for users without any organization membership"
]
}
}
@@ -0,0 +1,22 @@
-- Create personal organizations for users who don't have any organization membership
-- This covers the default seed user (login: 'user', email: 'test@mail.dest')
-- and any other users who may exist without an organization
INSERT INTO tv_auth.organizations (name, slug, owner_id, is_personal)
SELECT
u.login || '''s workspace',
'org-' || substr(md5(random()::text), 1, 8),
u.id,
1
FROM tv_auth.users u
WHERE NOT EXISTS (
SELECT 1 FROM tv_auth.organization_members om WHERE om.email = u.email
)
ON CONFLICT DO NOTHING;
-- Add these users as owners of their new personal organizations
INSERT INTO tv_auth.organization_members (organization_id, email, role)
SELECT o.id, u.email, 'owner'
FROM tv_auth.organizations o
JOIN tv_auth.users u ON u.id = o.owner_id
WHERE o.is_personal = 1
ON CONFLICT (organization_id, email) DO NOTHING;
+12
View File
@@ -171,6 +171,18 @@ Docker will pull the images, start the database, run migrations, and launch the
Go to [http://localhost:8888](http://localhost:8888) in your browser. You'll see the login screen.
### Configure the API server
Before logging in, you need to tell the web app where the API server is running. Click the **server settings** icon on the login page and add the API server URL:
```
http://localhost:1725
```
This is the API server that handles authentication, projects, tasks, and all backend operations. The web app (port 8888) serves the frontend, while the API server (port 1725) handles the data.
### Log in with the default user
The database migration creates a default user so you can log in right away:
- **Login:** `user`
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "taskview-ce-monorepo",
"version": "1.42.3",
"version": "1.42.5",
"private": true,
"description": "TaskView CE monorepo containing web, API, and packages",
"workspaces": [
@@ -22,6 +22,31 @@ afterAll(async () => {
await deleteAllGoals()
})
describe('Default user has a personal organization', () => {
it('default user (login: user, email: test@mail.dest) should have at least one organization', async () => {
const orgs = await user1Api.organizations.fetch()
expect(orgs.length).toBeGreaterThan(0)
const personal = orgs.find(o => (o as any).isPersonal === 1)
expect(personal).toBeTruthy()
expect(personal!.name).toContain('workspace')
})
it('default user should be an owner of their personal organization', async () => {
const orgs = await user1Api.organizations.fetch()
const personal = orgs.find(o => (o as any).isPersonal === 1)
expect(personal).toBeTruthy()
const members = await user1Api.organizations.fetchMembers(personal!.id)
const owner = members.find(m => m.email === user1Email)
expect(owner).toBeTruthy()
expect(owner!.role).toBe('owner')
})
})
describe('Organizations: creation and management', () => {
let createdOrgId: number
+1 -1
View File
@@ -2,7 +2,7 @@
"name": "web-nuxt-ui",
"private": true,
"type": "module",
"version": "1.42.3",
"version": "1.42.5",
"scripts": {
"dev": "vite",
"build:packages": "pnpm --filter taskview-db-schemas build && pnpm --filter taskview-api build",
@@ -146,7 +146,7 @@ async function handleSubmit() {
})
emit('success', result.data.access)
redirectToUser(router)
await redirectToUser(router)
}
} else {
await $api.post('/module/auth/send-login-code', { email: state.email })
@@ -123,7 +123,7 @@ async function onSubmit() {
emit('success', result.data.access)
redirectToUser(router)
await redirectToUser(router)
}
} catch (error: unknown) {
const axiosError = error as { response?: { status?: number } }