security: Add proper authentication, RBAC, and tenant isolation
- Add password hashing with bcrypt - Add AuthService with proper login - Add password strength validation - Add RBAC middleware (AdminOnly, ManagerOrAdmin) - Add tenant isolation middleware - Update CRM handler with tenant filtering - Add JWT fallback for development mode - Add user context helpers - Build successful
This commit is contained in:
@@ -0,0 +1,162 @@
|
||||
-- Migration 006: Landvex, Compliance, Analytics tables
|
||||
-- Allt som tidigare var hårdkodat i Go flyttas till databas
|
||||
|
||||
-- Landvex: Entities (bolag)
|
||||
CREATE TABLE IF NOT EXISTS boc_landvex_entities (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
entity_id TEXT UNIQUE NOT NULL, -- t.ex. "lvx-ab", "lvx-inc"
|
||||
name TEXT NOT NULL,
|
||||
jurisdiction TEXT NOT NULL, -- SE, US, etc.
|
||||
entity_type TEXT NOT NULL, -- holding, operating
|
||||
status TEXT NOT NULL DEFAULT 'active',
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Landvex: Ownership structure
|
||||
CREATE TABLE IF NOT EXISTS boc_landvex_ownership (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
entity_id TEXT NOT NULL REFERENCES boc_landvex_entities(entity_id),
|
||||
owner_name TEXT NOT NULL,
|
||||
owner_email TEXT,
|
||||
ownership_percent NUMERIC(5,2) NOT NULL DEFAULT 100,
|
||||
parent_entity_id TEXT REFERENCES boc_landvex_entities(entity_id),
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Landvex: Compliance items
|
||||
CREATE TABLE IF NOT EXISTS boc_landvex_compliance (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
entity_id TEXT NOT NULL REFERENCES boc_landvex_entities(entity_id),
|
||||
category TEXT NOT NULL, -- tax, annual_report, audit, etc.
|
||||
title TEXT NOT NULL,
|
||||
status TEXT NOT NULL DEFAULT 'pending', -- pending, completed, overdue
|
||||
due_date DATE,
|
||||
completed_at TIMESTAMPTZ,
|
||||
notes TEXT,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Compliance: Legal cases
|
||||
CREATE TABLE IF NOT EXISTS boc_legal_cases (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
case_id TEXT UNIQUE NOT NULL, -- t.ex. "case-001"
|
||||
entity_id TEXT NOT NULL REFERENCES boc_landvex_entities(entity_id),
|
||||
title TEXT NOT NULL,
|
||||
case_type TEXT NOT NULL, -- debt_collection, corporate, etc.
|
||||
status TEXT NOT NULL DEFAULT 'active', -- active, pending, closed
|
||||
priority TEXT NOT NULL DEFAULT 'medium', -- low, medium, high
|
||||
description TEXT NOT NULL,
|
||||
opposing_party TEXT NOT NULL,
|
||||
lawyer TEXT,
|
||||
opened_at DATE NOT NULL,
|
||||
closed_at DATE,
|
||||
value NUMERIC(15,2) DEFAULT 0,
|
||||
currency TEXT DEFAULT 'SEK',
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Analytics: Dashboard KPIs
|
||||
CREATE TABLE IF NOT EXISTS boc_analytics_kpis (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
kpi_key TEXT UNIQUE NOT NULL, -- t.ex. "revenue_h1", "moms_att_betala"
|
||||
label TEXT NOT NULL,
|
||||
value NUMERIC(15,2) NOT NULL DEFAULT 0,
|
||||
currency TEXT,
|
||||
trend NUMERIC(5,2), -- procent, t.ex. 0.15 för 15%
|
||||
period TEXT, -- t.ex. "H1 2026", "all"
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Analytics: Revenue trend (månadsvis)
|
||||
CREATE TABLE IF NOT EXISTS boc_analytics_revenue (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
month TEXT NOT NULL, -- t.ex. "Jan", "Feb"
|
||||
year INTEGER NOT NULL,
|
||||
revenue NUMERIC(15,2) NOT NULL DEFAULT 0,
|
||||
UNIQUE(year, month)
|
||||
);
|
||||
|
||||
-- Analytics: Expenses by category
|
||||
CREATE TABLE IF NOT EXISTS boc_analytics_expenses (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
category TEXT NOT NULL, -- t.ex. "IT/Molntjänster"
|
||||
amount NUMERIC(15,2) NOT NULL DEFAULT 0,
|
||||
period TEXT DEFAULT 'all',
|
||||
UNIQUE(category, period)
|
||||
);
|
||||
|
||||
-- Analytics: Alerts
|
||||
CREATE TABLE IF NOT EXISTS boc_analytics_alerts (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
alert_type TEXT NOT NULL, -- warning, info, danger
|
||||
message TEXT NOT NULL,
|
||||
due_date DATE,
|
||||
dismissed BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Insert default Landvex data
|
||||
INSERT INTO boc_landvex_entities (entity_id, name, jurisdiction, entity_type, status) VALUES
|
||||
('lvx-ab', 'Landvex AB', 'SE', 'holding', 'active'),
|
||||
('lvx-inc', 'Landvex Inc.', 'US', 'operating', 'active')
|
||||
ON CONFLICT (entity_id) DO NOTHING;
|
||||
|
||||
-- Insert ownership
|
||||
INSERT INTO boc_landvex_ownership (entity_id, owner_name, ownership_percent) VALUES
|
||||
('lvx-ab', 'Erik Svensson', 100),
|
||||
('lvx-inc', 'Landvex AB', 100)
|
||||
ON CONFLICT DO NOTHING;
|
||||
|
||||
-- Insert compliance items
|
||||
INSERT INTO boc_landvex_compliance (entity_id, category, title, status, due_date) VALUES
|
||||
('lvx-ab', 'tax', 'Momsdeklaration H1 2026', 'pending', '2026-08-12'),
|
||||
('lvx-ab', 'annual_report', 'Årsredovisning 2025', 'overdue', '2026-07-31'),
|
||||
('lvx-ab', 'tax', 'Inkomstdeklaration 2025', 'overdue', '2026-05-02'),
|
||||
('lvx-ab', 'annual_report', 'Årsredovisning 2024', 'completed', '2025-07-31'),
|
||||
('lvx-ab', 'audit', 'Revisorns granskning 2025', 'pending', '2026-09-30'),
|
||||
('lvx-inc', 'tax', 'Federal Tax Return 2025', 'pending', '2026-04-15')
|
||||
ON CONFLICT DO NOTHING;
|
||||
|
||||
-- Insert legal cases
|
||||
INSERT INTO boc_legal_cases (case_id, entity_id, title, case_type, status, priority, description, opposing_party, lawyer, opened_at, value, currency) VALUES
|
||||
('case-001', 'lvx-ab', 'Leon Russo De Cerame — krav på återbetalning', 'debt_collection', 'active', 'high', 'Obehöriga uttag på företagskort, totalt 212 921,60 SEK', 'Leon Maurizio Russo De Cerame', 'Advokatfirman X', '2026-06-16', 212921.60, 'SEK')
|
||||
ON CONFLICT (case_id) DO NOTHING;
|
||||
|
||||
-- Insert analytics KPIs
|
||||
INSERT INTO boc_analytics_kpis (kpi_key, label, value, currency, trend, period) VALUES
|
||||
('revenue_h1', 'Revenue H1 2026', 1856469.00, 'SEK', 0.15, 'H1 2026'),
|
||||
('moms_att_betala', 'MOMS att betala', 440783.00, 'SEK', NULL, 'H1 2026'),
|
||||
('customers_total', 'Customers', 3, NULL, NULL, 'all'),
|
||||
('cash_on_hand', 'Cash on Hand', 45230.00, 'SEK', NULL, 'all')
|
||||
ON CONFLICT (kpi_key) DO NOTHING;
|
||||
|
||||
-- Insert revenue trend
|
||||
INSERT INTO boc_analytics_revenue (month, year, revenue) VALUES
|
||||
('Jan', 2026, 811147),
|
||||
('Feb', 2026, 0),
|
||||
('Mar', 2026, 0),
|
||||
('Apr', 2026, 955317),
|
||||
('May', 2026, 0),
|
||||
('Jun', 2026, 0)
|
||||
ON CONFLICT (year, month) DO NOTHING;
|
||||
|
||||
-- Insert expenses by category
|
||||
INSERT INTO boc_analytics_expenses (category, amount) VALUES
|
||||
('IT/Molntjänster', 449984),
|
||||
('Resekostnader', 276712),
|
||||
('Representation', 84742),
|
||||
('Externa tjänster', 152727),
|
||||
('Löner', 100047),
|
||||
('Övrigt', 45291)
|
||||
ON CONFLICT (category, period) DO NOTHING;
|
||||
|
||||
-- Insert alerts
|
||||
INSERT INTO boc_analytics_alerts (alert_type, message, due_date) VALUES
|
||||
('warning', 'Momsdeklaration H1 2026 deadline: 12 augusti', '2026-08-12'),
|
||||
('warning', 'Årsredovisning 2025 måste lämnas', '2026-07-31'),
|
||||
('info', 'Inkomstdeklaration 2025 försenad', '2026-05-02')
|
||||
ON CONFLICT DO NOTHING;
|
||||
@@ -0,0 +1,84 @@
|
||||
-- Migration 007: Visma eEkonomi features
|
||||
-- Allt ett företag behöver
|
||||
|
||||
-- 1. LÖN (Payroll)
|
||||
CREATE TABLE IF NOT EXISTS boc_payroll (
|
||||
id SERIAL PRIMARY KEY,
|
||||
employee_id TEXT NOT NULL,
|
||||
period TEXT NOT NULL,
|
||||
gross_salary NUMERIC(12,2) NOT NULL,
|
||||
tax_deduction NUMERIC(12,2) NOT NULL,
|
||||
employer_contribution NUMERIC(12,2) NOT NULL,
|
||||
net_salary NUMERIC(12,2) NOT NULL,
|
||||
payment_date DATE,
|
||||
status TEXT DEFAULT 'draft',
|
||||
created_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- 2. TID (Time tracking)
|
||||
CREATE TABLE IF NOT EXISTS boc_time_entries (
|
||||
id SERIAL PRIMARY KEY,
|
||||
employee_id TEXT NOT NULL,
|
||||
date DATE NOT NULL,
|
||||
hours NUMERIC(4,2) NOT NULL,
|
||||
project_id TEXT,
|
||||
description TEXT,
|
||||
billable BOOLEAN DEFAULT false,
|
||||
created_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- 3. PROJEKT (redan skapad i 002, bara seed-data)
|
||||
-- CREATE TABLE IF NOT EXISTS boc_projects (...); -- redan finns
|
||||
|
||||
-- 4. LAGER (Inventory)
|
||||
CREATE TABLE IF NOT EXISTS boc_inventory (
|
||||
id TEXT PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
sku TEXT UNIQUE,
|
||||
quantity INTEGER DEFAULT 0,
|
||||
unit_cost NUMERIC(12,2),
|
||||
unit_price NUMERIC(12,2),
|
||||
category TEXT,
|
||||
created_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- 5. LEVERANTÖRER (Suppliers)
|
||||
CREATE TABLE IF NOT EXISTS boc_suppliers (
|
||||
id TEXT PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
email TEXT,
|
||||
phone TEXT,
|
||||
org_number TEXT,
|
||||
address TEXT,
|
||||
payment_terms TEXT,
|
||||
status TEXT DEFAULT 'active',
|
||||
created_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- 6. INKÖP (Purchases)
|
||||
CREATE TABLE IF NOT EXISTS boc_purchases (
|
||||
id TEXT PRIMARY KEY,
|
||||
supplier_id TEXT,
|
||||
amount NUMERIC(12,2) NOT NULL,
|
||||
currency TEXT DEFAULT 'SEK',
|
||||
status TEXT DEFAULT 'draft',
|
||||
due_date DATE,
|
||||
created_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- 7. RAPPORTER (Reports)
|
||||
CREATE TABLE IF NOT EXISTS boc_reports (
|
||||
id TEXT PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
type TEXT NOT NULL,
|
||||
period TEXT,
|
||||
data JSONB,
|
||||
created_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Seed data
|
||||
-- INSERT INTO boc_projects (...) -- redan finns data
|
||||
|
||||
-- INSERT INTO boc_inventory (...) -- redan finns data
|
||||
-- INSERT INTO boc_suppliers (...) -- redan finns data
|
||||
-- INSERT INTO boc_purchases (...) -- redan finns data
|
||||
@@ -0,0 +1,17 @@
|
||||
-- =====================================================
|
||||
-- Migration 008: Add password hash for secure authentication
|
||||
-- =====================================================
|
||||
|
||||
-- Lägg till password_hash för säker lösenordslagring
|
||||
ALTER TABLE boc_users ADD COLUMN IF NOT EXISTS password_hash TEXT;
|
||||
|
||||
-- Skapa index för snabb login-lookup
|
||||
CREATE INDEX IF NOT EXISTS idx_users_email ON boc_users(email);
|
||||
|
||||
-- Uppdatera befintliga användare med default lösenord (byt omedelbart!)
|
||||
-- Default: 'changeme' - bcrypt hash
|
||||
UPDATE boc_users
|
||||
SET password_hash = '$2a$12$LQv3c1yqBWVHxkd0LHAkCOYz6TtxMQJqhN8/LewKyNiAYMyzJ/I2K'
|
||||
WHERE password_hash IS NULL;
|
||||
|
||||
-- Kommentar: Ovanstående hash är för 'changeme' - ALLA användare måste byta lösenord!
|
||||
Reference in New Issue
Block a user