/ docker / init-db.sql
init-db.sql
  1  -- Asteroid Radio Database Initialization Script
  2  -- PostgreSQL Schema for persistent storage
  3  
  4  -- Enable UUID extension for generating unique IDs
  5  CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
  6  
  7  -- Users table
  8  CREATE TABLE IF NOT EXISTS "USERS" (
  9      _id SERIAL PRIMARY KEY,
 10      username VARCHAR(255) UNIQUE NOT NULL,
 11      email VARCHAR(255) UNIQUE NOT NULL,
 12      "password-hash" TEXT NOT NULL,
 13      role VARCHAR(50) DEFAULT 'listener',
 14      active integer DEFAULT 1,
 15      "created-date" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
 16      "last-login" TIMESTAMP,
 17      CONSTRAINT valid_role CHECK (role IN ('listener', 'dj', 'admin'))
 18  );
 19  
 20  -- Create index on username and email for faster lookups
 21  CREATE INDEX idx_users_username ON "USERS"(username);
 22  CREATE INDEX idx_users_email ON "USERS"(email);
 23  
 24  -- Tracks table
 25  CREATE TABLE IF NOT EXISTS tracks (
 26      _id SERIAL PRIMARY KEY,
 27      title VARCHAR(500) NOT NULL,
 28      artist VARCHAR(500),
 29      album VARCHAR(500),
 30      duration INTEGER DEFAULT 0,
 31      format VARCHAR(50),
 32      bitrate integer,
 33      "file-path" TEXT NOT NULL UNIQUE,
 34      "play-count" INTEGER DEFAULT 0,
 35      "added-date" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
 36      "last-played" TIMESTAMP
 37  );
 38  
 39  -- Create indexes for common queries
 40  CREATE INDEX idx_tracks_artist ON tracks(artist);
 41  CREATE INDEX idx_tracks_album ON tracks(album);
 42  CREATE INDEX idx_tracks_title ON tracks(title);
 43  
 44  -- Playlists table
 45  CREATE TABLE IF NOT EXISTS playlists (
 46      _id SERIAL PRIMARY KEY,
 47      "user-id" INTEGER NOT NULL REFERENCES "USERS"(_id) ON DELETE CASCADE,
 48      name VARCHAR(255) NOT NULL,
 49      description TEXT,
 50      "created-date" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
 51      "modified-date" TIMESTAMP DEFAULT CURRENT_TIMESTAMP
 52  );
 53  
 54  -- Create index on user_id for faster user playlist lookups
 55  CREATE INDEX idx_playlists_user_id ON playlists("user-id");
 56  
 57  -- Playlist tracks junction table (many-to-many relationship)
 58  CREATE TABLE IF NOT EXISTS playlist_tracks (
 59      _id SERIAL PRIMARY KEY,
 60      playlist_id INTEGER NOT NULL REFERENCES playlists(_id) ON DELETE CASCADE,
 61      track_id INTEGER NOT NULL REFERENCES tracks(_id) ON DELETE CASCADE,
 62      position INTEGER NOT NULL,
 63      added_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
 64      UNIQUE(playlist_id, track_id, "position")
 65  );
 66  
 67  -- Create indexes for playlist track queries
 68  CREATE INDEX idx_playlist_tracks_playlist_id ON playlist_tracks(playlist_id);
 69  CREATE INDEX idx_playlist_tracks_track_id ON playlist_tracks(track_id);
 70  
 71  -- Sessions table (for Radiance session management)
 72  -- CREATE TABLE IF NOT EXISTS sessions (
 73  --     _id VARCHAR(255) PRIMARY KEY,
 74  --     "user_id INTEGER REFERENCES users(id) ON DELETE CASCADE,
 75  --     data JSONB,
 76  --     created_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
 77  --     expires_at TIMESTAMP NOT NULL
 78  -- );
 79  
 80  -- Create index on user_id and expires_at
 81  -- CREATE INDEX idx_sessions_user_id ON sessions(user_id);
 82  -- CREATE INDEX idx_sessions_expires_at ON sessions(expires_at);
 83  
 84  -- Create default admin user (password: admin - CHANGE THIS!)
 85  -- Password hash for 'admin' using bcrypt
 86  INSERT INTO "USERS" (username, email, "password-hash", role, active)
 87  -- VALUES ('admin', 'admin@asteroid.radio', '$2a$12$LQv3c1yqBWVHxkd0LHAkCOYz6TtxMQJqhN8/LewY5GyYqYqYqYqYq', 'admin', 1)
 88  VALUES ('admin', 'admin@asteroid.radio','8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918', 'admin', 1)
 89  ON CONFLICT (username) DO NOTHING;
 90  
 91  -- Create a test listener user
 92  INSERT INTO "USERS" (username, email, "password-hash", role, active)
 93  VALUES ('listener', 'listener@asteroid.radio', '$2a$12$LQv3c1yqBWVHxkd0LHAkCOYz6TtxMQJqhN8/LewY5GyYqYqYqYqYq', 'listener', 1);
 94  
 95  -- Grant necessary permissions
 96  GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO asteroid;
 97  GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO asteroid;
 98  
 99  -- Create function to update modified_date automatically
100  CREATE OR REPLACE FUNCTION update_modified_date()
101  RETURNS TRIGGER AS $$
102  BEGIN
103      NEW.modified_date = CURRENT_TIMESTAMP;
104      RETURN NEW;
105  END;
106  $$ LANGUAGE plpgsql;
107  
108  -- Create trigger for playlists table
109  CREATE TRIGGER update_playlists_modified_date
110      BEFORE UPDATE ON playlists
111      FOR EACH ROW
112      EXECUTE FUNCTION update_modified_date();
113  
114  -- Success message
115  DO $$
116  BEGIN
117      RAISE NOTICE 'Asteroid Radio database initialized successfully!';
118      RAISE NOTICE 'Database: asteroid';
119      RAISE NOTICE 'User: asteroid';
120      RAISE NOTICE 'Default admin user created: admin / admin (CHANGE PASSWORD!)';
121  END $$;