Add latest changes
Dieser Commit ist enthalten in:
69
migrations/completed/001_hardware_id_cleanup.sql
Normale Datei
69
migrations/completed/001_hardware_id_cleanup.sql
Normale Datei
@@ -0,0 +1,69 @@
|
||||
-- Hardware ID Cleanup Migration
|
||||
-- Phase 1: Add new columns alongside old ones
|
||||
|
||||
-- 1. Update sessions table
|
||||
ALTER TABLE sessions
|
||||
ADD COLUMN IF NOT EXISTS machine_name VARCHAR(255),
|
||||
ADD COLUMN IF NOT EXISTS hardware_fingerprint VARCHAR(255);
|
||||
|
||||
-- 2. Update device_registrations table
|
||||
ALTER TABLE device_registrations
|
||||
ADD COLUMN IF NOT EXISTS machine_name VARCHAR(255),
|
||||
ADD COLUMN IF NOT EXISTS hardware_fingerprint TEXT;
|
||||
|
||||
-- 3. Update license_tokens table
|
||||
ALTER TABLE license_tokens
|
||||
ADD COLUMN IF NOT EXISTS machine_name VARCHAR(255),
|
||||
ADD COLUMN IF NOT EXISTS hardware_fingerprint VARCHAR(255);
|
||||
|
||||
-- 4. Update license_heartbeats table (partitioned)
|
||||
ALTER TABLE license_heartbeats
|
||||
ADD COLUMN IF NOT EXISTS machine_name VARCHAR(255),
|
||||
ADD COLUMN IF NOT EXISTS hardware_fingerprint VARCHAR(255);
|
||||
|
||||
-- 5. Update activation_events table
|
||||
ALTER TABLE activation_events
|
||||
ADD COLUMN IF NOT EXISTS machine_name VARCHAR(255),
|
||||
ADD COLUMN IF NOT EXISTS hardware_fingerprint VARCHAR(255),
|
||||
ADD COLUMN IF NOT EXISTS previous_hardware_fingerprint VARCHAR(255);
|
||||
|
||||
-- 6. Update active_sessions table
|
||||
ALTER TABLE active_sessions
|
||||
ADD COLUMN IF NOT EXISTS machine_name VARCHAR(255),
|
||||
ADD COLUMN IF NOT EXISTS hardware_fingerprint VARCHAR(255);
|
||||
|
||||
-- 7. Update license_sessions table
|
||||
ALTER TABLE license_sessions
|
||||
ADD COLUMN IF NOT EXISTS machine_name VARCHAR(255),
|
||||
ADD COLUMN IF NOT EXISTS hardware_fingerprint VARCHAR(255);
|
||||
|
||||
-- 8. Update session_history table
|
||||
ALTER TABLE session_history
|
||||
ADD COLUMN IF NOT EXISTS machine_name VARCHAR(255),
|
||||
ADD COLUMN IF NOT EXISTS hardware_fingerprint VARCHAR(255);
|
||||
|
||||
-- Copy existing data to new columns
|
||||
-- For now, we'll copy hardware_id to hardware_fingerprint
|
||||
-- machine_name will be populated by the application
|
||||
|
||||
UPDATE sessions SET hardware_fingerprint = hardware_id WHERE hardware_fingerprint IS NULL;
|
||||
UPDATE device_registrations SET hardware_fingerprint = hardware_id WHERE hardware_fingerprint IS NULL;
|
||||
UPDATE license_tokens SET hardware_fingerprint = hardware_id WHERE hardware_fingerprint IS NULL;
|
||||
UPDATE license_heartbeats SET hardware_fingerprint = hardware_id WHERE hardware_fingerprint IS NULL;
|
||||
UPDATE activation_events SET hardware_fingerprint = hardware_id WHERE hardware_fingerprint IS NULL;
|
||||
UPDATE activation_events SET previous_hardware_fingerprint = previous_hardware_id WHERE previous_hardware_fingerprint IS NULL;
|
||||
UPDATE active_sessions SET hardware_fingerprint = hardware_id WHERE hardware_fingerprint IS NULL;
|
||||
UPDATE license_sessions SET hardware_fingerprint = hardware_id WHERE hardware_fingerprint IS NULL;
|
||||
UPDATE session_history SET hardware_fingerprint = hardware_id WHERE hardware_fingerprint IS NULL;
|
||||
|
||||
-- Create indexes for new columns
|
||||
CREATE INDEX IF NOT EXISTS idx_sessions_hardware_fingerprint ON sessions(hardware_fingerprint);
|
||||
CREATE INDEX IF NOT EXISTS idx_device_registrations_hardware_fingerprint ON device_registrations(hardware_fingerprint);
|
||||
CREATE INDEX IF NOT EXISTS idx_license_tokens_hardware_fingerprint ON license_tokens(hardware_fingerprint);
|
||||
CREATE INDEX IF NOT EXISTS idx_license_heartbeats_hardware_fingerprint ON license_heartbeats(hardware_fingerprint, timestamp DESC);
|
||||
CREATE INDEX IF NOT EXISTS idx_active_sessions_hardware_fingerprint ON active_sessions(hardware_fingerprint);
|
||||
CREATE INDEX IF NOT EXISTS idx_license_sessions_hardware_fingerprint ON license_sessions(license_id, hardware_fingerprint);
|
||||
CREATE INDEX IF NOT EXISTS idx_session_history_hardware_fingerprint ON session_history(hardware_fingerprint);
|
||||
|
||||
-- Note: Old columns are NOT dropped yet. This will be done in a later migration
|
||||
-- after verifying the system works with new columns.
|
||||
38
migrations/completed/002_remove_old_hardware_columns.sql
Normale Datei
38
migrations/completed/002_remove_old_hardware_columns.sql
Normale Datei
@@ -0,0 +1,38 @@
|
||||
-- Remove old hardware columns after migration to new names
|
||||
-- This should only be run after all clients have been updated!
|
||||
|
||||
-- 1. Drop old columns from sessions table
|
||||
ALTER TABLE sessions DROP COLUMN IF EXISTS hardware_id;
|
||||
|
||||
-- 2. Drop old columns from device_registrations table
|
||||
ALTER TABLE device_registrations DROP COLUMN IF EXISTS hardware_id;
|
||||
|
||||
-- 3. Drop old columns from license_tokens table
|
||||
ALTER TABLE license_tokens DROP COLUMN IF EXISTS hardware_id;
|
||||
|
||||
-- 4. Drop old columns from license_heartbeats table (partitioned)
|
||||
ALTER TABLE license_heartbeats DROP COLUMN IF EXISTS hardware_id;
|
||||
|
||||
-- 5. Drop old columns from activation_events table
|
||||
ALTER TABLE activation_events
|
||||
DROP COLUMN IF EXISTS hardware_id,
|
||||
DROP COLUMN IF EXISTS previous_hardware_id;
|
||||
|
||||
-- 6. Drop old columns from active_sessions table
|
||||
ALTER TABLE active_sessions DROP COLUMN IF EXISTS hardware_id;
|
||||
|
||||
-- 7. Drop old columns from license_sessions table
|
||||
ALTER TABLE license_sessions DROP COLUMN IF EXISTS hardware_id;
|
||||
|
||||
-- 8. Drop old columns from session_history table
|
||||
ALTER TABLE session_history DROP COLUMN IF EXISTS hardware_id;
|
||||
|
||||
-- Drop old indexes that referenced hardware_id
|
||||
DROP INDEX IF EXISTS idx_device_hardware;
|
||||
DROP INDEX IF EXISTS idx_hardware;
|
||||
DROP INDEX IF EXISTS idx_heartbeat_hardware_time;
|
||||
DROP INDEX IF EXISTS idx_license_sessions_license_hardware;
|
||||
|
||||
-- Note: The activations table in the license server database
|
||||
-- still uses machine_id and hardware_hash columns.
|
||||
-- Those are handled separately in the license server.
|
||||
27
migrations/completed/003_migrate_activations_table.sql
Normale Datei
27
migrations/completed/003_migrate_activations_table.sql
Normale Datei
@@ -0,0 +1,27 @@
|
||||
-- Migrate activations table to new column names
|
||||
|
||||
-- Add new columns
|
||||
ALTER TABLE activations
|
||||
ADD COLUMN IF NOT EXISTS machine_name VARCHAR(255),
|
||||
ADD COLUMN IF NOT EXISTS hardware_fingerprint VARCHAR(255);
|
||||
|
||||
-- Copy data from old to new columns
|
||||
UPDATE activations
|
||||
SET machine_name = COALESCE(device_name, machine_id),
|
||||
hardware_fingerprint = hardware_hash
|
||||
WHERE machine_name IS NULL OR hardware_fingerprint IS NULL;
|
||||
|
||||
-- Make new columns NOT NULL after data is copied
|
||||
ALTER TABLE activations
|
||||
ALTER COLUMN machine_name SET NOT NULL,
|
||||
ALTER COLUMN hardware_fingerprint SET NOT NULL;
|
||||
|
||||
-- Drop old columns
|
||||
ALTER TABLE activations
|
||||
DROP COLUMN IF EXISTS machine_id,
|
||||
DROP COLUMN IF EXISTS hardware_hash,
|
||||
DROP COLUMN IF EXISTS device_name;
|
||||
|
||||
-- Update any indexes
|
||||
CREATE INDEX IF NOT EXISTS idx_activations_machine_name ON activations(machine_name);
|
||||
CREATE INDEX IF NOT EXISTS idx_activations_hardware_fingerprint ON activations(hardware_fingerprint);
|
||||
241
migrations/completed/004_device_management_cleanup.sql
Normale Datei
241
migrations/completed/004_device_management_cleanup.sql
Normale Datei
@@ -0,0 +1,241 @@
|
||||
-- =====================================================
|
||||
-- Migration: Device Management System Cleanup
|
||||
-- Date: 2025-01-03
|
||||
-- Purpose: Consolidate device tracking into single source of truth
|
||||
-- =====================================================
|
||||
|
||||
-- STEP 1: Backup existing data
|
||||
-- =====================================================
|
||||
CREATE TABLE IF NOT EXISTS backup_device_data_20250103 AS
|
||||
SELECT
|
||||
'activations' as source_table,
|
||||
a.id,
|
||||
a.license_id,
|
||||
COALESCE(a.device_name, a.machine_id) as device_name,
|
||||
a.hardware_hash as hardware_fingerprint,
|
||||
a.first_seen as first_activated_at,
|
||||
a.last_seen as last_seen_at,
|
||||
a.is_active,
|
||||
a.os_info,
|
||||
a.app_version
|
||||
FROM activations a
|
||||
UNION ALL
|
||||
SELECT
|
||||
'device_registrations' as source_table,
|
||||
dr.id,
|
||||
dr.license_id,
|
||||
dr.device_name,
|
||||
dr.hardware_id as hardware_fingerprint,
|
||||
dr.first_seen as first_activated_at,
|
||||
dr.last_seen as last_seen_at,
|
||||
dr.is_active,
|
||||
dr.operating_system::jsonb as os_info,
|
||||
NULL as app_version
|
||||
FROM device_registrations dr;
|
||||
|
||||
-- STEP 2: Standardize device_registrations table
|
||||
-- =====================================================
|
||||
-- Add missing columns to device_registrations
|
||||
ALTER TABLE device_registrations
|
||||
ADD COLUMN IF NOT EXISTS hardware_fingerprint VARCHAR(255),
|
||||
ADD COLUMN IF NOT EXISTS app_version VARCHAR(20),
|
||||
ADD COLUMN IF NOT EXISTS metadata JSONB DEFAULT '{}',
|
||||
ADD COLUMN IF NOT EXISTS first_activated_at TIMESTAMP WITH TIME ZONE,
|
||||
ADD COLUMN IF NOT EXISTS last_seen_at TIMESTAMP WITH TIME ZONE;
|
||||
|
||||
-- Migrate existing hardware_id to hardware_fingerprint
|
||||
UPDATE device_registrations
|
||||
SET hardware_fingerprint = hardware_id
|
||||
WHERE hardware_fingerprint IS NULL AND hardware_id IS NOT NULL;
|
||||
|
||||
-- Migrate timestamp columns
|
||||
UPDATE device_registrations
|
||||
SET first_activated_at = first_seen,
|
||||
last_seen_at = last_seen
|
||||
WHERE first_activated_at IS NULL OR last_seen_at IS NULL;
|
||||
|
||||
-- STEP 3: Migrate data from activations to device_registrations
|
||||
-- =====================================================
|
||||
-- Insert activations that don't exist in device_registrations
|
||||
INSERT INTO device_registrations (
|
||||
license_id,
|
||||
hardware_fingerprint,
|
||||
device_name,
|
||||
device_type,
|
||||
operating_system,
|
||||
first_activated_at,
|
||||
last_seen_at,
|
||||
is_active,
|
||||
ip_address,
|
||||
user_agent,
|
||||
app_version,
|
||||
metadata
|
||||
)
|
||||
SELECT
|
||||
a.license_id,
|
||||
a.hardware_hash as hardware_fingerprint,
|
||||
COALESCE(a.device_name, a.machine_id) as device_name,
|
||||
CASE
|
||||
WHEN a.os_info->>'os' ILIKE '%windows%' THEN 'desktop'
|
||||
WHEN a.os_info->>'os' ILIKE '%mac%' THEN 'desktop'
|
||||
WHEN a.os_info->>'os' ILIKE '%linux%' THEN 'desktop'
|
||||
ELSE 'unknown'
|
||||
END as device_type,
|
||||
a.os_info->>'os' as operating_system,
|
||||
a.first_seen,
|
||||
a.last_seen,
|
||||
a.is_active,
|
||||
NULL as ip_address,
|
||||
NULL as user_agent,
|
||||
a.app_version,
|
||||
a.os_info as metadata
|
||||
FROM activations a
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM device_registrations dr
|
||||
WHERE dr.license_id = a.license_id
|
||||
AND dr.hardware_fingerprint = a.hardware_hash
|
||||
);
|
||||
|
||||
-- Update existing device_registrations with latest data from activations
|
||||
UPDATE device_registrations dr
|
||||
SET
|
||||
last_seen_at = GREATEST(dr.last_seen_at, a.last_seen),
|
||||
is_active = a.is_active,
|
||||
app_version = COALESCE(a.app_version, dr.app_version),
|
||||
metadata = COALESCE(dr.metadata, '{}')::jsonb || COALESCE(a.os_info, '{}')::jsonb
|
||||
FROM activations a
|
||||
WHERE dr.license_id = a.license_id
|
||||
AND dr.hardware_fingerprint = a.hardware_hash
|
||||
AND a.last_seen > dr.last_seen_at;
|
||||
|
||||
-- STEP 4: Standardize licenses table
|
||||
-- =====================================================
|
||||
-- Remove duplicate device limit columns, keep only device_limit
|
||||
ALTER TABLE licenses DROP COLUMN IF EXISTS max_devices;
|
||||
ALTER TABLE licenses DROP COLUMN IF EXISTS max_activations;
|
||||
|
||||
-- Ensure device_limit has proper constraints
|
||||
ALTER TABLE licenses
|
||||
DROP CONSTRAINT IF EXISTS licenses_device_limit_check,
|
||||
ADD CONSTRAINT licenses_device_limit_check CHECK (device_limit >= 1);
|
||||
|
||||
-- Rename max_concurrent_sessions to concurrent_sessions_limit for clarity
|
||||
ALTER TABLE licenses
|
||||
RENAME COLUMN max_concurrent_sessions TO concurrent_sessions_limit;
|
||||
|
||||
-- Update constraint to reference device_limit
|
||||
ALTER TABLE licenses
|
||||
DROP CONSTRAINT IF EXISTS check_concurrent_sessions,
|
||||
ADD CONSTRAINT check_concurrent_sessions CHECK (concurrent_sessions_limit <= device_limit);
|
||||
|
||||
-- STEP 5: Clean up session tables
|
||||
-- =====================================================
|
||||
-- Consolidate into single license_sessions table
|
||||
-- First, backup existing session data
|
||||
CREATE TABLE IF NOT EXISTS backup_sessions_20250103 AS
|
||||
SELECT
|
||||
id,
|
||||
license_id,
|
||||
license_key,
|
||||
session_id,
|
||||
username,
|
||||
computer_name,
|
||||
hardware_id,
|
||||
ip_address,
|
||||
user_agent,
|
||||
app_version,
|
||||
started_at,
|
||||
last_heartbeat,
|
||||
ended_at,
|
||||
is_active
|
||||
FROM sessions;
|
||||
|
||||
-- Add missing columns to license_sessions
|
||||
ALTER TABLE license_sessions
|
||||
ADD COLUMN IF NOT EXISTS device_registration_id INTEGER REFERENCES device_registrations(id),
|
||||
ADD COLUMN IF NOT EXISTS ended_at TIMESTAMP WITH TIME ZONE,
|
||||
ADD COLUMN IF NOT EXISTS end_reason VARCHAR(50),
|
||||
ADD COLUMN IF NOT EXISTS user_agent TEXT;
|
||||
|
||||
-- Link license_sessions to device_registrations
|
||||
UPDATE license_sessions ls
|
||||
SET device_registration_id = dr.id
|
||||
FROM device_registrations dr
|
||||
WHERE ls.license_id = dr.license_id
|
||||
AND ls.hardware_id = dr.hardware_fingerprint
|
||||
AND ls.device_registration_id IS NULL;
|
||||
|
||||
-- STEP 6: Create indexes for performance
|
||||
-- =====================================================
|
||||
CREATE INDEX IF NOT EXISTS idx_device_registrations_license_fingerprint
|
||||
ON device_registrations(license_id, hardware_fingerprint);
|
||||
CREATE INDEX IF NOT EXISTS idx_device_registrations_active
|
||||
ON device_registrations(license_id, is_active) WHERE is_active = true;
|
||||
CREATE INDEX IF NOT EXISTS idx_device_registrations_last_seen
|
||||
ON device_registrations(last_seen_at DESC);
|
||||
|
||||
-- STEP 7: Drop old columns (after verification)
|
||||
-- =====================================================
|
||||
-- These will be dropped after confirming migration success
|
||||
ALTER TABLE device_registrations
|
||||
DROP COLUMN IF EXISTS hardware_id,
|
||||
DROP COLUMN IF EXISTS first_seen,
|
||||
DROP COLUMN IF EXISTS last_seen;
|
||||
|
||||
-- STEP 8: Create views for backwards compatibility (temporary)
|
||||
-- =====================================================
|
||||
CREATE OR REPLACE VIEW v_activations AS
|
||||
SELECT
|
||||
id,
|
||||
license_id,
|
||||
device_name as machine_id,
|
||||
device_name,
|
||||
hardware_fingerprint as hardware_hash,
|
||||
first_activated_at as activation_date,
|
||||
first_activated_at as first_seen,
|
||||
last_seen_at as last_seen,
|
||||
last_seen_at as last_heartbeat,
|
||||
is_active,
|
||||
metadata as os_info,
|
||||
operating_system,
|
||||
app_version,
|
||||
ip_address,
|
||||
user_agent,
|
||||
device_type,
|
||||
deactivated_at,
|
||||
deactivated_by
|
||||
FROM device_registrations;
|
||||
|
||||
-- STEP 9: Update system_api_key usage tracking
|
||||
-- =====================================================
|
||||
UPDATE system_api_key
|
||||
SET last_used_at = CURRENT_TIMESTAMP,
|
||||
usage_count = usage_count + 1
|
||||
WHERE id = 1;
|
||||
|
||||
-- STEP 10: Add audit log entry for migration
|
||||
-- =====================================================
|
||||
INSERT INTO audit_log (
|
||||
timestamp,
|
||||
username,
|
||||
action,
|
||||
entity_type,
|
||||
entity_id,
|
||||
additional_info
|
||||
) VALUES (
|
||||
CURRENT_TIMESTAMP,
|
||||
'system',
|
||||
'device_management_migration',
|
||||
'database',
|
||||
0,
|
||||
'Consolidated device management system - merged activations into device_registrations'
|
||||
);
|
||||
|
||||
-- Summary of changes:
|
||||
-- 1. Consolidated device tracking into device_registrations table
|
||||
-- 2. Removed duplicate columns: max_devices, max_activations
|
||||
-- 3. Standardized on device_limit column
|
||||
-- 4. Renamed max_concurrent_sessions to concurrent_sessions_limit
|
||||
-- 5. Added proper foreign key relationships
|
||||
-- 6. Created backwards compatibility view for activations
|
||||
-- 7. Improved indexing for performance
|
||||
26
migrations/completed/005_cleanup_old_device_structures.sql
Normale Datei
26
migrations/completed/005_cleanup_old_device_structures.sql
Normale Datei
@@ -0,0 +1,26 @@
|
||||
-- Migration: Cleanup old device management structures
|
||||
-- Date: 2025-01-03
|
||||
-- Description: Remove old tables and compatibility views after successful migration
|
||||
|
||||
BEGIN;
|
||||
|
||||
-- Drop compatibility view
|
||||
DROP VIEW IF EXISTS v_activations CASCADE;
|
||||
|
||||
-- Drop old activations table
|
||||
DROP TABLE IF EXISTS activations CASCADE;
|
||||
|
||||
-- Drop any backup tables if they exist
|
||||
DROP TABLE IF EXISTS device_registrations_backup CASCADE;
|
||||
DROP TABLE IF EXISTS licenses_backup CASCADE;
|
||||
|
||||
-- Drop old columns that might still exist
|
||||
ALTER TABLE licenses DROP COLUMN IF EXISTS max_devices CASCADE;
|
||||
ALTER TABLE licenses DROP COLUMN IF EXISTS max_activations CASCADE;
|
||||
|
||||
-- Add comment to document the cleanup
|
||||
COMMENT ON TABLE device_registrations IS 'Main table for device management - replaces old activations table';
|
||||
COMMENT ON COLUMN device_registrations.hardware_fingerprint IS 'Unique hardware identifier - replaces old hardware_id/hardware_hash';
|
||||
COMMENT ON COLUMN device_registrations.device_name IS 'Device name - replaces old machine_name/machine_id';
|
||||
|
||||
COMMIT;
|
||||
27
migrations/completed/006_cleanup_license_sessions_hardware_id.sql
Normale Datei
27
migrations/completed/006_cleanup_license_sessions_hardware_id.sql
Normale Datei
@@ -0,0 +1,27 @@
|
||||
-- Migration: Cleanup license_sessions hardware_id column
|
||||
-- Date: 2025-01-03
|
||||
-- Description: Migrate hardware_id data to hardware_fingerprint and remove old column
|
||||
|
||||
BEGIN;
|
||||
|
||||
-- Copy data from hardware_id to hardware_fingerprint where it's null
|
||||
UPDATE license_sessions
|
||||
SET hardware_fingerprint = hardware_id
|
||||
WHERE hardware_fingerprint IS NULL AND hardware_id IS NOT NULL;
|
||||
|
||||
-- Make hardware_fingerprint NOT NULL (it should have data now)
|
||||
ALTER TABLE license_sessions
|
||||
ALTER COLUMN hardware_fingerprint SET NOT NULL;
|
||||
|
||||
-- Drop the old hardware_id column
|
||||
ALTER TABLE license_sessions
|
||||
DROP COLUMN hardware_id CASCADE;
|
||||
|
||||
-- Update the index to use hardware_fingerprint
|
||||
DROP INDEX IF EXISTS idx_license_sessions_license_hardware;
|
||||
CREATE INDEX idx_license_sessions_license_hardware ON license_sessions(license_id, hardware_fingerprint);
|
||||
|
||||
-- Add comment
|
||||
COMMENT ON COLUMN license_sessions.hardware_fingerprint IS 'Unique hardware identifier for the session';
|
||||
|
||||
COMMIT;
|
||||
23
migrations/completed/007_cleanup_session_history_hardware_id.sql
Normale Datei
23
migrations/completed/007_cleanup_session_history_hardware_id.sql
Normale Datei
@@ -0,0 +1,23 @@
|
||||
-- Migration: Cleanup session_history hardware_id column
|
||||
-- Date: 2025-01-03
|
||||
-- Description: Migrate hardware_id data to hardware_fingerprint and remove old column
|
||||
|
||||
BEGIN;
|
||||
|
||||
-- Copy data from hardware_id to hardware_fingerprint where it's null
|
||||
UPDATE session_history
|
||||
SET hardware_fingerprint = hardware_id
|
||||
WHERE hardware_fingerprint IS NULL AND hardware_id IS NOT NULL;
|
||||
|
||||
-- Make hardware_fingerprint NOT NULL
|
||||
ALTER TABLE session_history
|
||||
ALTER COLUMN hardware_fingerprint SET NOT NULL;
|
||||
|
||||
-- Drop the old hardware_id column
|
||||
ALTER TABLE session_history
|
||||
DROP COLUMN hardware_id CASCADE;
|
||||
|
||||
-- Add comment
|
||||
COMMENT ON COLUMN session_history.hardware_fingerprint IS 'Unique hardware identifier for the session';
|
||||
|
||||
COMMIT;
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren