@semantq/auth
Advanced tools
| // models/migrations/mysql/0000-migrations-table.js | ||
| export const up = async (db) => { | ||
| await db.raw(` | ||
| CREATE TABLE IF NOT EXISTS schema_migrations ( | ||
| id INT AUTO_INCREMENT PRIMARY KEY, | ||
| migration_name VARCHAR(255) NOT NULL, | ||
| batch INT NOT NULL, | ||
| run_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, | ||
| UNIQUE KEY unique_migration (migration_name) | ||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; | ||
| `); | ||
| }; | ||
| export const down = async (db) => { | ||
| await db.raw(`DROP TABLE IF EXISTS schema_migrations`); | ||
| }; |
| // models/migrations/mysql/0000-migrations-table.js | ||
| export const up = async (db) => { | ||
| await db.raw(` | ||
| CREATE TABLE IF NOT EXISTS schema_migrations ( | ||
| id INT AUTO_INCREMENT PRIMARY KEY, | ||
| migration_name VARCHAR(255) NOT NULL, | ||
| batch INT NOT NULL, | ||
| run_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, | ||
| UNIQUE KEY unique_migration (migration_name) | ||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; | ||
| `); | ||
| }; | ||
| export const down = async (db) => { | ||
| await db.raw(`DROP TABLE IF EXISTS schema_migrations`); | ||
| }; |
@@ -1,3 +0,6 @@ | ||
| export const up = async (pool) => { | ||
| await pool.query(` | ||
| // models/migrations/mysql/0001-users.js | ||
| export const up = async (db) => { | ||
| // USERS TABLE | ||
| await db.query(` | ||
| CREATE TABLE IF NOT EXISTS users ( | ||
@@ -8,3 +11,3 @@ id INT AUTO_INCREMENT PRIMARY KEY, | ||
| name VARCHAR(100), | ||
| surname VARCHAR(100), | ||
| surname VARCHAR(100), | ||
| is_verified BOOLEAN DEFAULT FALSE, | ||
@@ -26,3 +29,4 @@ verification_token VARCHAR(255), | ||
| await pool.query(` | ||
| // AUTH LOGS TABLE | ||
| await db.query(` | ||
| CREATE TABLE IF NOT EXISTS auth_logs ( | ||
@@ -47,13 +51,13 @@ id INT AUTO_INCREMENT PRIMARY KEY, | ||
| INDEX idx_created_at (created_at) | ||
| ) ENGINE=InnoDB; | ||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; | ||
| `); | ||
| }; | ||
| export const down = async (pool) => { | ||
| export const down = async (db) => { | ||
| // Drop dependent tables first | ||
| await pool.query(`DROP TABLE IF EXISTS sessions`); | ||
| await pool.query(`DROP TABLE IF EXISTS auth_logs`); | ||
| await pool.query(`DROP TABLE IF EXISTS products`); | ||
| // Then drop referenced tables | ||
| await pool.query(`DROP TABLE IF EXISTS users`); | ||
| await db.query(`DROP TABLE IF EXISTS sessions`); | ||
| await db.query(`DROP TABLE IF EXISTS auth_logs`); | ||
| await db.query(`DROP TABLE IF EXISTS products`); | ||
| // Then drop referenced table | ||
| await db.query(`DROP TABLE IF EXISTS users`); | ||
| }; |
@@ -1,7 +0,10 @@ | ||
| export const up = async (pool) => { | ||
| await pool.query(` | ||
| // models/migrations/mysql/0002-sessions.js | ||
| export const up = async (db) => { | ||
| // Use raw() for all DDL statements | ||
| await db.raw(` | ||
| CREATE TABLE IF NOT EXISTS sessions ( | ||
| id INT AUTO_INCREMENT PRIMARY KEY, | ||
| user_id INT NOT NULL, | ||
| token VARCHAR(512) NOT NULL, -- Increased length for modern tokens | ||
| token VARCHAR(512) NOT NULL, | ||
| device_info VARCHAR(255), | ||
@@ -11,3 +14,3 @@ ip_address VARCHAR(45), | ||
| revoked_at TIMESTAMP NULL, | ||
| expires_at TIMESTAMP NOT NULL, -- Explicit expiration | ||
| expires_at TIMESTAMP NOT NULL, | ||
| created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, | ||
@@ -17,3 +20,3 @@ updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, | ||
| INDEX idx_user_id (user_id), | ||
| INDEX idx_token (token(64)), -- Prefix index for token | ||
| INDEX idx_token (token(64)), | ||
| INDEX idx_expires (expires_at), | ||
@@ -23,5 +26,4 @@ INDEX idx_active_sessions (user_id, is_revoked, expires_at) | ||
| `); | ||
| // Add session cleanup procedure for MySQL | ||
| await pool.query(` | ||
| await db.raw(` | ||
| CREATE EVENT IF NOT EXISTS session_cleanup | ||
@@ -35,5 +37,5 @@ ON SCHEDULE EVERY 1 DAY | ||
| export const down = async (pool) => { | ||
| await pool.query(`DROP EVENT IF EXISTS session_cleanup`); | ||
| await pool.query(`DROP TABLE IF EXISTS sessions`); | ||
| export const down = async (db) => { | ||
| await db.raw(`DROP EVENT IF EXISTS session_cleanup`); | ||
| await db.raw(`DROP TABLE IF EXISTS sessions`); | ||
| }; |
@@ -1,3 +0,6 @@ | ||
| export const up = async (pool) => { | ||
| await pool.query(` | ||
| // models/migrations/mysql/0001-users.js | ||
| export const up = async (db) => { | ||
| // USERS TABLE | ||
| await db.query(` | ||
| CREATE TABLE IF NOT EXISTS users ( | ||
@@ -8,3 +11,3 @@ id INT AUTO_INCREMENT PRIMARY KEY, | ||
| name VARCHAR(100), | ||
| surname VARCHAR(100), | ||
| surname VARCHAR(100), | ||
| is_verified BOOLEAN DEFAULT FALSE, | ||
@@ -26,3 +29,4 @@ verification_token VARCHAR(255), | ||
| await pool.query(` | ||
| // AUTH LOGS TABLE | ||
| await db.query(` | ||
| CREATE TABLE IF NOT EXISTS auth_logs ( | ||
@@ -47,13 +51,13 @@ id INT AUTO_INCREMENT PRIMARY KEY, | ||
| INDEX idx_created_at (created_at) | ||
| ) ENGINE=InnoDB; | ||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; | ||
| `); | ||
| }; | ||
| export const down = async (pool) => { | ||
| export const down = async (db) => { | ||
| // Drop dependent tables first | ||
| await pool.query(`DROP TABLE IF EXISTS sessions`); | ||
| await pool.query(`DROP TABLE IF EXISTS auth_logs`); | ||
| await pool.query(`DROP TABLE IF EXISTS products`); | ||
| // Then drop referenced tables | ||
| await pool.query(`DROP TABLE IF EXISTS users`); | ||
| await db.query(`DROP TABLE IF EXISTS sessions`); | ||
| await db.query(`DROP TABLE IF EXISTS auth_logs`); | ||
| await db.query(`DROP TABLE IF EXISTS products`); | ||
| // Then drop referenced table | ||
| await db.query(`DROP TABLE IF EXISTS users`); | ||
| }; |
@@ -1,7 +0,10 @@ | ||
| export const up = async (pool) => { | ||
| await pool.query(` | ||
| // models/migrations/mysql/0002-sessions.js | ||
| export const up = async (db) => { | ||
| // Use raw() for all DDL statements | ||
| await db.raw(` | ||
| CREATE TABLE IF NOT EXISTS sessions ( | ||
| id INT AUTO_INCREMENT PRIMARY KEY, | ||
| user_id INT NOT NULL, | ||
| token VARCHAR(512) NOT NULL, -- Increased length for modern tokens | ||
| token VARCHAR(512) NOT NULL, | ||
| device_info VARCHAR(255), | ||
@@ -11,3 +14,3 @@ ip_address VARCHAR(45), | ||
| revoked_at TIMESTAMP NULL, | ||
| expires_at TIMESTAMP NOT NULL, -- Explicit expiration | ||
| expires_at TIMESTAMP NOT NULL, | ||
| created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, | ||
@@ -17,3 +20,3 @@ updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, | ||
| INDEX idx_user_id (user_id), | ||
| INDEX idx_token (token(64)), -- Prefix index for token | ||
| INDEX idx_token (token(64)), | ||
| INDEX idx_expires (expires_at), | ||
@@ -23,5 +26,4 @@ INDEX idx_active_sessions (user_id, is_revoked, expires_at) | ||
| `); | ||
| // Add session cleanup procedure for MySQL | ||
| await pool.query(` | ||
| await db.raw(` | ||
| CREATE EVENT IF NOT EXISTS session_cleanup | ||
@@ -35,5 +37,5 @@ ON SCHEDULE EVERY 1 DAY | ||
| export const down = async (pool) => { | ||
| await pool.query(`DROP EVENT IF EXISTS session_cleanup`); | ||
| await pool.query(`DROP TABLE IF EXISTS sessions`); | ||
| export const down = async (db) => { | ||
| await db.raw(`DROP EVENT IF EXISTS session_cleanup`); | ||
| await db.raw(`DROP TABLE IF EXISTS sessions`); | ||
| }; |
| // semantq_auth/models/mysql/user.js | ||
| // FIX: Corrected path to import the mysqlAdapter from the main semantq_server's models/adapters | ||
| import mysqlAdapter from '../../../../models/adapters/mysql.js'; // This path goes up 4 levels to semantq_server/models/adapters/mysql.js | ||
| import mysqlAdapter from '../../../../../models/adapters/mysql.js'; // This path goes up 4 levels to semantq_server/models/adapters/mysql.js | ||
@@ -5,0 +5,0 @@ // Find user by email |
+1
-1
| { | ||
| "name": "@semantq/auth", | ||
| "version": "1.0.2", | ||
| "version": "1.0.3", | ||
| "description": "Full stack (MySQL/Supabase) authentication package for Semantq JS Framework", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -19,3 +19,3 @@ import express from 'express'; | ||
| router.post('/signup', signupHandler); | ||
| router.post('/confirm-email', confirmEmailHandler); | ||
| router.post('/confirm', confirmEmailHandler); | ||
| router.post('/login', loginHandler); | ||
@@ -22,0 +22,0 @@ router.post('/forgot-password', forgotPasswordHandler); |
@@ -127,3 +127,3 @@ // semantq_auth/services/email.js | ||
| } | ||
| const confirmationUrl = `${process.env.UI_BASE_URL}/confirm-email?token=${token}`; | ||
| const confirmationUrl = `${process.env.FRONTEND_BASE_URL}/auth/confirm?token=${token}`; | ||
| const subject = `Confirm Your ${process.env.BRAND_NAME} Account`; | ||
@@ -204,3 +204,3 @@ | ||
| } | ||
| const resetUrl = `${process.env.UI_BASE_URL}/reset-password?token=${token}`; | ||
| const resetUrl = `${process.env.FRONTEND_BASE_URL}/auth/reset?token=${token}`; | ||
| const subject = `Reset Your ${process.env.BRAND_NAME} Password`; | ||
@@ -207,0 +207,0 @@ |
| export const up = async (pool) => { | ||
| await pool.query(` | ||
| CREATE TABLE IF NOT EXISTS products ( | ||
| id INT AUTO_INCREMENT PRIMARY KEY, | ||
| sku VARCHAR(100) UNIQUE NOT NULL, | ||
| name VARCHAR(255) NOT NULL, | ||
| slug VARCHAR(255) UNIQUE NOT NULL, | ||
| description TEXT, | ||
| short_description VARCHAR(500), | ||
| status ENUM('draft','active','archived','out_of_stock') DEFAULT 'draft', | ||
| price DECIMAL(12,2) UNSIGNED, | ||
| compare_price DECIMAL(12,2) UNSIGNED, | ||
| cost_price DECIMAL(12,2) UNSIGNED, | ||
| stock_quantity INT UNSIGNED DEFAULT 0, | ||
| weight DECIMAL(10,2) UNSIGNED, | ||
| length DECIMAL(10,2) UNSIGNED, | ||
| width DECIMAL(10,2) UNSIGNED, | ||
| height DECIMAL(10,2) UNSIGNED, | ||
| attributes JSON, | ||
| metadata JSON, | ||
| seo_title VARCHAR(255), | ||
| seo_description VARCHAR(500), | ||
| created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, | ||
| updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, | ||
| deleted_at TIMESTAMP NULL, | ||
| INDEX idx_slug (slug), | ||
| INDEX idx_status (status), | ||
| INDEX idx_price (price), | ||
| INDEX idx_stock (stock_quantity), | ||
| FULLTEXT INDEX ft_search (name, description, short_description) | ||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; | ||
| `); | ||
| // Add stock alert trigger | ||
| await pool.query(` | ||
| CREATE TRIGGER IF NOT EXISTS product_stock_alert | ||
| AFTER UPDATE ON products | ||
| FOR EACH ROW | ||
| BEGIN | ||
| IF NEW.stock_quantity < 5 AND OLD.stock_quantity >= 5 THEN | ||
| INSERT INTO notifications (type, entity_type, entity_id, message) | ||
| VALUES ('low_stock', 'product', NEW.id, | ||
| CONCAT('Low stock alert for product ', NEW.name)); | ||
| END IF; | ||
| END; | ||
| `); | ||
| }; | ||
| export const down = async (pool) => { | ||
| await pool.query(`DROP TRIGGER IF EXISTS product_stock_alert`); | ||
| await pool.query(`DROP TABLE IF EXISTS products`); | ||
| }; |
| export const up = async (pool) => { | ||
| await pool.query(` | ||
| CREATE TABLE IF NOT EXISTS test_table ( | ||
| id INT AUTO_INCREMENT PRIMARY KEY, | ||
| test_field VARCHAR(100) NOT NULL | ||
| ) | ||
| `); | ||
| }; | ||
| export const down = async (pool) => { | ||
| await pool.query(`DROP TABLE IF EXISTS test_table`); | ||
| }; |
| export const up = async (pool) => { | ||
| await pool.query(` | ||
| CREATE TABLE IF NOT EXISTS products ( | ||
| id INT AUTO_INCREMENT PRIMARY KEY, | ||
| sku VARCHAR(100) UNIQUE NOT NULL, | ||
| name VARCHAR(255) NOT NULL, | ||
| slug VARCHAR(255) UNIQUE NOT NULL, | ||
| description TEXT, | ||
| short_description VARCHAR(500), | ||
| status ENUM('draft','active','archived','out_of_stock') DEFAULT 'draft', | ||
| price DECIMAL(12,2) UNSIGNED, | ||
| compare_price DECIMAL(12,2) UNSIGNED, | ||
| cost_price DECIMAL(12,2) UNSIGNED, | ||
| stock_quantity INT UNSIGNED DEFAULT 0, | ||
| weight DECIMAL(10,2) UNSIGNED, | ||
| length DECIMAL(10,2) UNSIGNED, | ||
| width DECIMAL(10,2) UNSIGNED, | ||
| height DECIMAL(10,2) UNSIGNED, | ||
| attributes JSON, | ||
| metadata JSON, | ||
| seo_title VARCHAR(255), | ||
| seo_description VARCHAR(500), | ||
| created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, | ||
| updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, | ||
| deleted_at TIMESTAMP NULL, | ||
| INDEX idx_slug (slug), | ||
| INDEX idx_status (status), | ||
| INDEX idx_price (price), | ||
| INDEX idx_stock (stock_quantity), | ||
| FULLTEXT INDEX ft_search (name, description, short_description) | ||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; | ||
| `); | ||
| // Add stock alert trigger | ||
| await pool.query(` | ||
| CREATE TRIGGER IF NOT EXISTS product_stock_alert | ||
| AFTER UPDATE ON products | ||
| FOR EACH ROW | ||
| BEGIN | ||
| IF NEW.stock_quantity < 5 AND OLD.stock_quantity >= 5 THEN | ||
| INSERT INTO notifications (type, entity_type, entity_id, message) | ||
| VALUES ('low_stock', 'product', NEW.id, | ||
| CONCAT('Low stock alert for product ', NEW.name)); | ||
| END IF; | ||
| END; | ||
| `); | ||
| }; | ||
| export const down = async (pool) => { | ||
| await pool.query(`DROP TRIGGER IF EXISTS product_stock_alert`); | ||
| await pool.query(`DROP TABLE IF EXISTS products`); | ||
| }; |
| export const up = async (pool) => { | ||
| await pool.query(` | ||
| CREATE TABLE IF NOT EXISTS test_table ( | ||
| id INT AUTO_INCREMENT PRIMARY KEY, | ||
| test_field VARCHAR(100) NOT NULL | ||
| ) | ||
| `); | ||
| }; | ||
| export const down = async (pool) => { | ||
| await pool.query(`DROP TABLE IF EXISTS test_table`); | ||
| }; |
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
50
-3.85%63211
-4.78%32
-5.88%1390
-5.7%