├── log └── .keep ├── storage └── .keep ├── tmp └── .keep ├── vendor └── .keep ├── lib ├── assets │ └── .keep ├── tasks │ └── .keep ├── queries │ ├── mysql │ │ ├── databases.sql │ │ └── database_schema.sql │ ├── psql │ │ └── databases.sql │ └── query.rb └── setup.rb ├── test ├── helpers │ └── .keep ├── mailers │ ├── .keep │ └── previews │ │ ├── reset_password_mailer_preview.rb │ │ └── activation_mailer_preview.rb ├── models │ └── .keep ├── system │ └── .keep ├── controllers │ └── .keep ├── fixtures │ ├── .keep │ └── files │ │ └── .keep ├── integration │ └── .keep ├── application_system_test_case.rb └── test_helper.rb ├── .ruby-version ├── app ├── assets │ ├── images │ │ └── .keep │ ├── javascripts │ │ ├── channels │ │ │ └── .keep │ │ ├── pages.js │ │ ├── cable.js │ │ └── application.js │ ├── config │ │ └── manifest.js │ └── stylesheets │ │ ├── about.scss │ │ ├── user_list.scss │ │ ├── dashboard.scss │ │ ├── semantic.scss │ │ ├── application.scss │ │ ├── db_server_card.scss │ │ ├── query.scss │ │ ├── result_table.scss │ │ ├── temp_db_server.scss │ │ ├── clickable-icon.scss │ │ ├── graph_line.scss │ │ ├── colors.scss │ │ ├── sql_results.scss │ │ ├── graph_word_cloud.scss │ │ └── database_schema_tree.scss ├── models │ ├── concerns │ │ └── .keep │ ├── application_record.rb │ ├── login_token.rb │ └── group_member.rb ├── controllers │ ├── concerns │ │ └── .keep │ ├── application_controller.rb │ └── pages_controller.rb ├── javascript │ ├── declarations │ │ ├── .gitkeep │ │ ├── REST.d.ts │ │ └── sql-query-identifier.d.ts │ ├── views │ │ ├── helper.ts │ │ └── ForgotPassword.tsx │ ├── api │ │ ├── status.ts │ │ ├── og_meta.ts │ │ ├── base.ts │ │ ├── admin.ts │ │ ├── sql_query.ts │ │ └── temp_db_server.ts │ ├── stores │ │ ├── router_store.ts │ │ └── status_store.ts │ ├── utils │ │ ├── listFilters.ts │ │ └── colors.ts │ ├── models │ │ ├── Results │ │ │ ├── MultiResult.ts │ │ │ └── RawResult.ts │ │ ├── Sql.ts │ │ ├── DbSchema.ts │ │ ├── Graphs │ │ │ ├── LineGraph.ts │ │ │ └── WordcloudGraph.ts │ │ ├── DbTable.ts │ │ ├── User.tsx │ │ ├── GroupMember.ts │ │ └── DbColumn.ts │ ├── components │ │ ├── Workbench │ │ │ ├── SqlResult │ │ │ │ ├── EmptyResult.tsx │ │ │ │ ├── SkippedResult.tsx │ │ │ │ ├── ErrorReport.tsx │ │ │ │ ├── PrismCode.tsx │ │ │ │ ├── PreviewImage.tsx │ │ │ │ └── SqlResult.tsx │ │ │ ├── DatabaseSchemaTree │ │ │ │ ├── SchemaItem.tsx │ │ │ │ ├── TableItem.tsx │ │ │ │ └── PlaceholderItem.tsx │ │ │ └── ResultPanel │ │ │ │ └── ResultPanelBody.tsx │ │ ├── Navigation │ │ │ └── Logout.tsx │ │ ├── SqlQueries │ │ │ └── SqlQueryErrors.tsx │ │ ├── Profile │ │ │ ├── SchemaQueries │ │ │ │ └── LoadMoreCard.tsx │ │ │ ├── DeleteAccount.tsx │ │ │ └── Groups │ │ │ │ └── GroupProps.tsx │ │ └── Dashboard │ │ │ └── AddDbServer.tsx │ ├── antlr │ │ ├── QuerySeparationGrammar.g4 │ │ ├── QuerySeparationGrammarVisitor.ts │ │ └── QuerySeparationGrammarListener.ts │ └── shared │ │ ├── DbSqlIcon.tsx │ │ ├── AddEntityButton.tsx │ │ ├── helpers.ts │ │ └── Tooltip.tsx ├── views │ ├── layouts │ │ ├── mailer.text.erb │ │ ├── application.html.erb │ │ └── mailer.html.erb │ ├── pages │ │ └── index.html.erb │ ├── activation_mailer │ │ └── activate_account.html.erb │ └── reset_password_mailer │ │ └── reset.html.erb ├── helpers │ ├── pages_helper.rb │ └── application_helper.rb ├── api │ ├── entities.rb │ ├── resources.rb │ ├── entities │ │ ├── group_user.rb │ │ ├── table.rb │ │ ├── database.rb │ │ ├── group_member.rb │ │ ├── og_meta.rb │ │ ├── query_result.rb │ │ ├── rails_index.rb │ │ ├── sql_query.rb │ │ ├── rails_foreign_key.rb │ │ ├── group.rb │ │ ├── db_server.rb │ │ ├── database_schema_query.rb │ │ ├── rails_column.rb │ │ ├── user.rb │ │ └── full_database.rb │ ├── resources │ │ ├── status.rb │ │ ├── login.rb │ │ ├── og_meta.rb │ │ └── admin.rb │ └── concerns │ │ └── error_handling.rb ├── jobs │ └── application_job.rb ├── channels │ └── application_cable │ │ ├── channel.rb │ │ └── connection.rb ├── mailers │ ├── application_mailer.rb │ ├── reset_password_mailer.rb │ └── activation_mailer.rb ├── seeders │ ├── seed_groups.rb │ ├── seed_users.rb │ └── seed_database_schema_queries.rb └── policies │ ├── application_policy.rb │ ├── database_schema_query_policy.rb │ ├── sql_query_policy.rb │ ├── user_policy.rb │ ├── db_server_policy.rb │ └── group_policy.rb ├── public ├── apple-touch-icon-precomposed.png ├── favicon.ico ├── apple-touch-icon.png ├── robots.txt ├── 500.html ├── 422.html └── 404.html ├── docs ├── logo.png ├── db-sql.gif └── security_concepts.md ├── spec └── fixtures │ └── database │ ├── mysql.cnf │ ├── mysql │ └── ninja_turtles_create.sql │ └── psql │ └── ninja_turtles_create.sql ├── docker-images ├── DB-SQL-Builder │ └── .gitignore ├── DB-SQL-Final │ └── Dockerfile └── Ubuntu-Ruby │ └── Dockerfile ├── Procfile ├── config ├── database.yml.travis ├── spring.rb ├── routes.rb ├── environment.rb ├── webpack │ ├── test.js │ ├── production.js │ ├── development.js │ └── environment.js ├── initializers │ ├── mime_types.rb │ ├── filter_parameter_logging.rb │ ├── application_controller_renderer.rb │ ├── cookies_serializer.rb │ ├── backtrace_silencers.rb │ ├── cors.rb │ ├── wrap_parameters.rb │ ├── inflections.rb │ ├── assets.rb │ └── content_security_policy.rb ├── boot.rb ├── cable.yml ├── application.rb ├── credentials.yml.enc ├── locales │ └── en.yml ├── storage.yml ├── database.yml └── puma.rb ├── bin ├── rake ├── generate_docs ├── rails ├── yarn ├── webpack ├── webpack-dev-server ├── pry ├── yri ├── haml ├── puma ├── sass ├── scss ├── thin ├── thor ├── tilt ├── yard ├── ldiff ├── rackup ├── yardoc ├── byebug ├── coderay ├── dotenv ├── gitlab ├── launchy ├── listen ├── maruku ├── marutex ├── pronto ├── pumactl ├── rspec ├── rubocop ├── sidekiq ├── spring ├── travis ├── annotate ├── htmldiff ├── httparty ├── nokogiri ├── ruby-parse ├── sidekiqmon ├── sprockets ├── ruby-rewrite ├── sass-convert ├── solargraph ├── gdb_wrapper ├── mailcatcher ├── rdebug-ide ├── sqlite3_ruby ├── update ├── reverse_markdown └── setup ├── swagger-ui-dist ├── favicon-16x16.png ├── favicon-32x32.png ├── swagger-ui.css.map ├── absolute-path.js ├── package.json ├── index.js └── README.md ├── .prettierrc ├── .babelrc ├── config.ru ├── db ├── migrate │ ├── 20190522190529_add_role_to_users.rb │ ├── 20200509090806_add_unique_index_to_users_email.rb │ ├── 20200512102511_remove_activated_from_users.rb │ ├── 20190512185709_add_username_to_db_connections.rb │ ├── 20190519222830_add_login_count_to_user.rb │ ├── 20200404090911_change_db_connections_to_db_servers.rb │ ├── 20190630115233_rename_initial_schema_db_connection.rb │ ├── 20230926151305_add_default_sql_limit_to_db_servers.rb │ ├── 20200410152508_add_foreign_key_constraints.rb │ ├── 20231030070138_change_default_sql_limit_to_db_servers.rb │ ├── 20210417105746_add_execution_time_to_sql_queries.rb │ ├── 20190530084410_add_reset_password_columns_to_users.rb │ ├── 20200410155552_add_query_stats_to_db_servers.rb │ ├── 20190523220405_add_activated_column_to_users.rb │ ├── 20190317172759_create_login_tokens.rb │ ├── 20190317172749_create_users.rb │ ├── 20190321070416_rename_attributes_db_connections.rb │ ├── 20200613181612_add_keys_to_users.rb │ ├── 20190512155558_add_foreign_key_constraint_to_active_storage_attachments_for_blob_id.active_storage.rb │ ├── 20190318190402_create_db_connections.rb │ ├── 20210416204537_create_active_storage_variant_records.active_storage.rb │ ├── 20200713092022_create_sql_queries.rb │ ├── 20210416204536_add_service_name_to_active_storage_blobs.active_storage.rb │ ├── 20210416071527_convert_composite_keys_to_indexed_fields.rb │ ├── 20200523222631_create_database_schema_queries.rb │ ├── 20200613154940_create_groups.rb │ └── 20200713091435_create_active_storage_tables.active_storage.rb └── seeds.rb ├── app.json ├── Rakefile ├── postcss.config.js ├── credentials.example.yml ├── db_servers.example.yaml ├── swagger_ui.js ├── Dockerfile ├── tsconfig.json ├── .travis.yml ├── tslint.json └── .gitignore /log/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /storage/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tmp/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vendor/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /lib/assets/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /lib/tasks/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/helpers/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/mailers/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/models/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/system/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.ruby-version: -------------------------------------------------------------------------------- 1 | ruby-3.0.2 -------------------------------------------------------------------------------- /app/assets/images/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/controllers/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/fixtures/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/integration/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/models/concerns/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/fixtures/files/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/controllers/concerns/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/assets/javascripts/channels/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/javascript/declarations/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/apple-touch-icon-precomposed.png: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /lib/queries/mysql/databases.sql: -------------------------------------------------------------------------------- 1 | SHOW DATABASES; -------------------------------------------------------------------------------- /app/views/layouts/mailer.text.erb: -------------------------------------------------------------------------------- 1 | <%= yield %> 2 | -------------------------------------------------------------------------------- /app/views/pages/index.html.erb: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /app/helpers/pages_helper.rb: -------------------------------------------------------------------------------- 1 | module PagesHelper 2 | end 3 | -------------------------------------------------------------------------------- /app/helpers/application_helper.rb: -------------------------------------------------------------------------------- 1 | module ApplicationHelper 2 | end 3 | -------------------------------------------------------------------------------- /docs/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lebalz/db-sql/HEAD/docs/logo.png -------------------------------------------------------------------------------- /lib/setup.rb: -------------------------------------------------------------------------------- 1 | class Setup 2 | def check() 3 | true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /spec/fixtures/database/mysql.cnf: -------------------------------------------------------------------------------- 1 | [mysqld] 2 | bind-address = 0.0.0.0 3 | ssl=0 -------------------------------------------------------------------------------- /docker-images/DB-SQL-Builder/.gitignore: -------------------------------------------------------------------------------- 1 | Gemfile* 2 | package.json 3 | yarn.lock 4 | -------------------------------------------------------------------------------- /docs/db-sql.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lebalz/db-sql/HEAD/docs/db-sql.gif -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | web: bundle exec rails s -p 3000 2 | webpacker: bin/webpack-dev-server -p 3035 -------------------------------------------------------------------------------- /app/api/entities.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Entities 4 | end 5 | -------------------------------------------------------------------------------- /app/api/resources.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Resources 4 | end 5 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lebalz/db-sql/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /config/database.yml.travis: -------------------------------------------------------------------------------- 1 | test: 2 | adapter: postgresql 3 | database: travis_ci_test 4 | -------------------------------------------------------------------------------- /public/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lebalz/db-sql/HEAD/public/apple-touch-icon.png -------------------------------------------------------------------------------- /app/controllers/application_controller.rb: -------------------------------------------------------------------------------- 1 | class ApplicationController < ActionController::Base 2 | end 3 | -------------------------------------------------------------------------------- /app/jobs/application_job.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class ApplicationJob < ActiveJob::Base 4 | end 5 | -------------------------------------------------------------------------------- /bin/rake: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require_relative '../config/boot' 3 | require 'rake' 4 | Rake.application.run 5 | -------------------------------------------------------------------------------- /swagger-ui-dist/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lebalz/db-sql/HEAD/swagger-ui-dist/favicon-16x16.png -------------------------------------------------------------------------------- /swagger-ui-dist/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lebalz/db-sql/HEAD/swagger-ui-dist/favicon-32x32.png -------------------------------------------------------------------------------- /app/controllers/pages_controller.rb: -------------------------------------------------------------------------------- 1 | class PagesController < ApplicationController 2 | def index 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file 2 | -------------------------------------------------------------------------------- /swagger-ui-dist/swagger-ui.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":[],"names":[],"mappings":"","file":"swagger-ui.css","sourceRoot":""} -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "arrowParens": "always", 4 | "printWidth": 110, 5 | "trailingComma": "none" 6 | } -------------------------------------------------------------------------------- /app/channels/application_cable/channel.rb: -------------------------------------------------------------------------------- 1 | module ApplicationCable 2 | class Channel < ActionCable::Channel::Base 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /config/spring.rb: -------------------------------------------------------------------------------- 1 | Spring.watch( 2 | ".ruby-version", 3 | ".rbenv-vars", 4 | "tmp/restart.txt", 5 | "tmp/caching-dev.txt" 6 | ) 7 | -------------------------------------------------------------------------------- /app/assets/config/manifest.js: -------------------------------------------------------------------------------- 1 | //= link_tree ../images 2 | //= link_directory ../javascripts .js 3 | //= link_directory ../stylesheets .css 4 | -------------------------------------------------------------------------------- /app/channels/application_cable/connection.rb: -------------------------------------------------------------------------------- 1 | module ApplicationCable 2 | class Connection < ActionCable::Connection::Base 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /bin/generate_docs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | # frozen_string_literal: true 4 | 5 | system('yardoc --private --protected app/models/*.rb') 6 | -------------------------------------------------------------------------------- /app/javascript/views/helper.ts: -------------------------------------------------------------------------------- 1 | export function isSafePassword(password: string) { 2 | return password.length > 7 && password.length < 73; 3 | } 4 | -------------------------------------------------------------------------------- /app/assets/stylesheets/about.scss: -------------------------------------------------------------------------------- 1 | .further-info { 2 | display: flex; 3 | flex-direction: row; 4 | justify-content: center; 5 | margin: 1em 0; 6 | } -------------------------------------------------------------------------------- /config/routes.rb: -------------------------------------------------------------------------------- 1 | Rails.application.routes.draw do 2 | mount API => '/api' 3 | 4 | get '*path', to: 'pages#index' 5 | root 'pages#index' 6 | end 7 | -------------------------------------------------------------------------------- /app/models/application_record.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class ApplicationRecord < ActiveRecord::Base 4 | self.abstract_class = true 5 | end 6 | -------------------------------------------------------------------------------- /app/assets/stylesheets/user_list.scss: -------------------------------------------------------------------------------- 1 | #userlist-commands{ 2 | display: flex; 3 | flex-direction: row; 4 | justify-content: space-between; 5 | flex-wrap: wrap; 6 | } -------------------------------------------------------------------------------- /config/environment.rb: -------------------------------------------------------------------------------- 1 | # Load the Rails application. 2 | require_relative 'application' 3 | 4 | # Initialize the Rails application. 5 | Rails.application.initialize! 6 | -------------------------------------------------------------------------------- /app/assets/stylesheets/dashboard.scss: -------------------------------------------------------------------------------- 1 | .db-server-overview { 2 | display: grid; 3 | grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); 4 | gap: 1em; 5 | } 6 | -------------------------------------------------------------------------------- /lib/queries/psql/databases.sql: -------------------------------------------------------------------------------- 1 | SELECT datname AS "databases" 2 | FROM pg_database 3 | WHERE 4 | datistemplate = false 5 | AND 6 | has_database_privilege(datname, 'CONNECT'); 7 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "@babel/env", 4 | "@babel/preset-react" 5 | ], 6 | "plugins": [ 7 | ["@babel/plugin-proposal-decorators", { "legacy": true }] 8 | ] 9 | } -------------------------------------------------------------------------------- /app/assets/javascripts/pages.js: -------------------------------------------------------------------------------- 1 | // Place all the behaviors and hooks related to the matching controller here. 2 | // All this logic will automatically be available in application.js. 3 | -------------------------------------------------------------------------------- /app/javascript/declarations/REST.d.ts: -------------------------------------------------------------------------------- 1 | export const enum REST { 2 | None = 'none', 3 | Requested = 'requested', 4 | Success = 'success', 5 | Error = 'error', 6 | Canceled = 'canceled' 7 | } -------------------------------------------------------------------------------- /config.ru: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # This file is used by Rack-based servers to start the application. 4 | 5 | require_relative 'config/environment' 6 | 7 | run Rails.application 8 | -------------------------------------------------------------------------------- /config/webpack/test.js: -------------------------------------------------------------------------------- 1 | process.env.NODE_ENV = process.env.NODE_ENV || 'development' 2 | 3 | const environment = require('./environment') 4 | 5 | module.exports = environment.toWebpackConfig() 6 | -------------------------------------------------------------------------------- /test/mailers/previews/reset_password_mailer_preview.rb: -------------------------------------------------------------------------------- 1 | class ResetPasswordMailerPreview < ActionMailer::Preview 2 | 3 | def reset 4 | ResetPasswordMailer.reset(User.last) 5 | end 6 | end -------------------------------------------------------------------------------- /app/api/entities/group_user.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Entities 4 | 5 | class GroupUser < Grape::Entity 6 | expose :id 7 | expose :email 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /app/mailers/application_mailer.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class ApplicationMailer < ActionMailer::Base 4 | default from: 'gbsl_fs-info@edubern365.ch' 5 | layout 'mailer' 6 | end 7 | -------------------------------------------------------------------------------- /config/webpack/production.js: -------------------------------------------------------------------------------- 1 | process.env.NODE_ENV = process.env.NODE_ENV || 'production' 2 | 3 | const environment = require('./environment') 4 | 5 | module.exports = environment.toWebpackConfig() 6 | -------------------------------------------------------------------------------- /config/initializers/mime_types.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new mime types for use in respond_to blocks: 4 | # Mime::Type.register "text/richtext", :rtf 5 | -------------------------------------------------------------------------------- /config/webpack/development.js: -------------------------------------------------------------------------------- 1 | process.env.NODE_ENV = process.env.NODE_ENV || 'development' 2 | 3 | const environment = require('./environment') 4 | 5 | module.exports = environment.toWebpackConfig() 6 | -------------------------------------------------------------------------------- /test/mailers/previews/activation_mailer_preview.rb: -------------------------------------------------------------------------------- 1 | class ActivationMailerPreview < ActionMailer::Preview 2 | 3 | def activate_account 4 | ActivationMailer.activate_account(User.last) 5 | end 6 | end -------------------------------------------------------------------------------- /app/assets/stylesheets/semantic.scss: -------------------------------------------------------------------------------- 1 | $font-family: 'Open Sans'; 2 | $font-url: 'https://fonts.googleapis.com/css?family=Open+Sans:400,400i,700,700i&subset=latin-ext'; 3 | 4 | @import "semantic-ui" 5 | -------------------------------------------------------------------------------- /db/migrate/20190522190529_add_role_to_users.rb: -------------------------------------------------------------------------------- 1 | class AddRoleToUsers < ActiveRecord::Migration[6.0] 2 | def change 3 | add_column :users, :role, :integer, default: User.roles[:user] 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200509090806_add_unique_index_to_users_email.rb: -------------------------------------------------------------------------------- 1 | class AddUniqueIndexToUsersEmail < ActiveRecord::Migration[6.0] 2 | def change 3 | add_index :users, [:email], unique: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200512102511_remove_activated_from_users.rb: -------------------------------------------------------------------------------- 1 | class RemoveActivatedFromUsers < ActiveRecord::Migration[6.0] 2 | def change 3 | 4 | remove_column :users, :activated, :boolean 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /test/application_system_test_case.rb: -------------------------------------------------------------------------------- 1 | require "test_helper" 2 | 3 | class ApplicationSystemTestCase < ActionDispatch::SystemTestCase 4 | driven_by :selenium, using: :chrome, screen_size: [1400, 1400] 5 | end 6 | -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "DB-SQL", 3 | "description": "Web based dbms for PostgreSQL and MySql", 4 | "scripts": { 5 | "dokku": { 6 | "postdeploy": "bundle exec rails db:migrate" 7 | } 8 | } 9 | } -------------------------------------------------------------------------------- /db/migrate/20190512185709_add_username_to_db_connections.rb: -------------------------------------------------------------------------------- 1 | class AddUsernameToDbConnections < ActiveRecord::Migration[6.0] 2 | def change 3 | add_column :db_connections, :username, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20190519222830_add_login_count_to_user.rb: -------------------------------------------------------------------------------- 1 | class AddLoginCountToUser < ActiveRecord::Migration[6.0] 2 | def change 3 | add_column :users, :login_count, :integer, default: 0 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200404090911_change_db_connections_to_db_servers.rb: -------------------------------------------------------------------------------- 1 | class ChangeDbConnectionsToDbServers < ActiveRecord::Migration[6.0] 2 | def change 3 | rename_table :db_connections, :db_servers 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /app/api/entities/table.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Entities 4 | class Table < Grape::Entity 5 | with_options(expose_nil: false) do 6 | expose :name 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /config/boot.rb: -------------------------------------------------------------------------------- 1 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) 2 | 3 | require 'bundler/setup' # Set up gems listed in the Gemfile. 4 | require 'bootsnap/setup' # Speed up boot time by caching expensive operations. 5 | -------------------------------------------------------------------------------- /db/migrate/20190630115233_rename_initial_schema_db_connection.rb: -------------------------------------------------------------------------------- 1 | class RenameInitialSchemaDbConnection < ActiveRecord::Migration[6.0] 2 | def change 3 | rename_column :db_connections, :initial_schema, :initial_table 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20230926151305_add_default_sql_limit_to_db_servers.rb: -------------------------------------------------------------------------------- 1 | class AddDefaultSqlLimitToDbServers < ActiveRecord::Migration[6.1] 2 | def change 3 | add_column :db_servers, :default_sql_limit, :integer, default: 10_000 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200410152508_add_foreign_key_constraints.rb: -------------------------------------------------------------------------------- 1 | class AddForeignKeyConstraints < ActiveRecord::Migration[6.0] 2 | def change 3 | add_foreign_key "login_tokens", "users" 4 | add_foreign_key "db_servers", "users" 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /config/cable.yml: -------------------------------------------------------------------------------- 1 | development: 2 | adapter: async 3 | 4 | test: 5 | adapter: test 6 | 7 | production: 8 | adapter: redis 9 | url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %> 10 | channel_prefix: db_sql_production 11 | -------------------------------------------------------------------------------- /config/initializers/filter_parameter_logging.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Configure sensitive parameters which will be filtered from the log file. 4 | Rails.application.config.filter_parameters += [:password] 5 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # Add your own tasks in files placed in lib/tasks ending in .rake, 2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. 3 | 4 | require_relative 'config/application' 5 | 6 | Rails.application.load_tasks 7 | -------------------------------------------------------------------------------- /app/api/entities/database.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Entities 4 | class Database < Grape::Entity 5 | with_options(expose_nil: false) do 6 | expose :name 7 | expose :db_server_id 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /db/migrate/20231030070138_change_default_sql_limit_to_db_servers.rb: -------------------------------------------------------------------------------- 1 | class ChangeDefaultSqlLimitToDbServers < ActiveRecord::Migration[6.1] 2 | def change 3 | change_column_default :db_servers, :default_sql_limit, from: 10_000, to: 500 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20210417105746_add_execution_time_to_sql_queries.rb: -------------------------------------------------------------------------------- 1 | class AddExecutionTimeToSqlQueries < ActiveRecord::Migration[6.1] 2 | def change 3 | add_column :sql_queries, :exec_time, :float 4 | add_column :sql_queries, :error, :json, default: [] 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /app/javascript/api/status.ts: -------------------------------------------------------------------------------- 1 | import api from './base'; 2 | import { AxiosPromise } from 'axios'; 3 | 4 | export interface Commit { 5 | commit: string; 6 | link: string; 7 | } 8 | 9 | export function getCommit(): AxiosPromise { 10 | return api.get('commit'); 11 | } -------------------------------------------------------------------------------- /app/javascript/stores/router_store.ts: -------------------------------------------------------------------------------- 1 | import { RouterStore as ReactRouterStore } from 'mobx-react-router'; 2 | import { Store } from './root_store'; 3 | 4 | class RouterStore extends ReactRouterStore implements Store { 5 | cleanup() {} 6 | } 7 | 8 | export default RouterStore; 9 | -------------------------------------------------------------------------------- /app/api/entities/group_member.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Entities 4 | class GroupMember < Grape::Entity 5 | expose :is_admin 6 | expose :is_outdated 7 | expose :user_id 8 | expose :created_at 9 | expose :updated_at 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /app/api/entities/og_meta.rb: -------------------------------------------------------------------------------- 1 | module Entities 2 | class OGMeta < Grape::Entity 3 | with_options(expose_nil: false) do 4 | expose :image 5 | expose :site_name 6 | expose :title 7 | expose :description 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /app/mailers/reset_password_mailer.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class ResetPasswordMailer < ApplicationMailer 4 | def reset(user) 5 | @user = user 6 | mail( 7 | to: @user.email, 8 | subject: "Reset DB SQL Password" 9 | ) 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /db/migrate/20190530084410_add_reset_password_columns_to_users.rb: -------------------------------------------------------------------------------- 1 | class AddResetPasswordColumnsToUsers < ActiveRecord::Migration[6.0] 2 | def change 3 | add_column :users, :reset_password_digest, :string 4 | add_column :users, :reset_password_mail_sent_at, :datetime 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /app/javascript/utils/listFilters.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @param ts array with potentially `undefined` members 3 | * @returns array without `undefined` values. 4 | */ 5 | export function rejectUndefined(ts: (T | undefined)[]): T[] { 6 | return ts.filter((t: T | undefined): t is T => t !== undefined); 7 | } -------------------------------------------------------------------------------- /config/initializers/application_controller_renderer.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # ActiveSupport::Reloader.to_prepare do 4 | # ApplicationController.renderer.defaults.merge!( 5 | # http_host: 'example.org', 6 | # https: false 7 | # ) 8 | # end 9 | -------------------------------------------------------------------------------- /db/migrate/20200410155552_add_query_stats_to_db_servers.rb: -------------------------------------------------------------------------------- 1 | class AddQueryStatsToDbServers < ActiveRecord::Migration[6.0] 2 | def change 3 | add_column :db_servers, :query_count, :integer, default: 0 4 | add_column :db_servers, :error_query_count, :integer, default: 0 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [ 3 | require('postcss-import'), 4 | require('postcss-flexbugs-fixes'), 5 | require('postcss-preset-env')({ 6 | autoprefixer: { 7 | flexbox: 'no-2009' 8 | }, 9 | stage: 3 10 | }) 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /config/initializers/cookies_serializer.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Specify a serializer for the signed and encrypted cookie jars. 4 | # Valid options are :json, :marshal, and :hybrid. 5 | Rails.application.config.action_dispatch.cookies_serializer = :json 6 | -------------------------------------------------------------------------------- /credentials.example.yml: -------------------------------------------------------------------------------- 1 | development: 2 | DB_SQL_DATABASE_USER: postgres 3 | DB_SQL_DATABASE_PASSWORD: "" 4 | SMTP_USERNAME: bla@foo.ch 5 | SMTP_PW: "" 6 | production: 7 | DB_SQL_DATABASE_USER: postgres 8 | DB_SQL_DATABASE_PASSWORD: "" 9 | SMTP_USERNAME: bla@blu.ch 10 | SMTP_PW: "" -------------------------------------------------------------------------------- /bin/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | if ENV['RAILS_ENV'] == 'test' 3 | require 'simplecov' 4 | SimpleCov.start 'rails' 5 | puts "required simplecov" 6 | end 7 | APP_PATH = File.expand_path('../config/application', __dir__) 8 | require_relative '../config/boot' 9 | require 'rails/commands' 10 | -------------------------------------------------------------------------------- /db_servers.example.yaml: -------------------------------------------------------------------------------- 1 | foobar: 2 | db_host: 'localhost' 3 | db_port: 3306 4 | db_type: :mysql 5 | db_username: 'root' 6 | db_password: 'foobar' 7 | db_initial_db: 'foo' 8 | db_initial_table: 'bar' 9 | app_user: 'test@user.ch' 10 | app_user_password: 'asdfasdf' 11 | foobar2: 12 | ... -------------------------------------------------------------------------------- /db/migrate/20190523220405_add_activated_column_to_users.rb: -------------------------------------------------------------------------------- 1 | class AddActivatedColumnToUsers < ActiveRecord::Migration[6.0] 2 | def change 3 | add_column :users, :activation_digest, :string 4 | add_column :users, :activated, :boolean, default: false 5 | add_column :users, :activated_at, :datetime 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /app/javascript/declarations/sql-query-identifier.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'sql-query-identifier' { 2 | export interface Command { 3 | end: number; 4 | executionType: string; 5 | start: number; 6 | text: string; 7 | ​​type: string; 8 | } 9 | export function identify(query: string): Command[]; 10 | } 11 | -------------------------------------------------------------------------------- /swagger_ui.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const express = require('express'); 3 | const logger = require('morgan'); 4 | 5 | 6 | const app = express(); 7 | 8 | app.use(logger('combined')); 9 | app.use(express.static('./swagger-ui-dist')); 10 | 11 | app.listen(4000); 12 | console.log('Visit http://localhost:4000'); 13 | -------------------------------------------------------------------------------- /db/migrate/20190317172759_create_login_tokens.rb: -------------------------------------------------------------------------------- 1 | class CreateLoginTokens < ActiveRecord::Migration[5.2] 2 | def change 3 | create_table :login_tokens, id: :uuid do |t| 4 | t.string :token 5 | t.belongs_to :user, type: :uuid, null: false, index: true 6 | 7 | t.timestamps 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Builder stage 2 | FROM lebalz/rails-full-builder:latest AS Builder 3 | 4 | # Final stage 5 | FROM lebalz/rails-full-final:latest 6 | 7 | # Additional setup your production image requires, e.g. adding more Alpine packages 8 | # RUN apk add .... 9 | 10 | USER app 11 | 12 | # Execute the Procfile 13 | CMD ["bin/run-dev.sh"] -------------------------------------------------------------------------------- /app/mailers/activation_mailer.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class ActivationMailer < ApplicationMailer 4 | 5 | def activate_account(user) 6 | @user = user 7 | mail( 8 | to: @user.email, 9 | subject: "DB SQL Account Activation", 10 | content_type: "text/html" 11 | ) 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /db/migrate/20190317172749_create_users.rb: -------------------------------------------------------------------------------- 1 | class CreateUsers < ActiveRecord::Migration[5.2] 2 | def change 3 | enable_extension 'uuid-ossp' 4 | enable_extension 'pgcrypto' 5 | create_table :users, id: :uuid do |t| 6 | t.string :email 7 | t.string :password_digest 8 | 9 | t.timestamps 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/test_helper.rb: -------------------------------------------------------------------------------- 1 | ENV['RAILS_ENV'] ||= 'test' 2 | require_relative '../config/environment' 3 | require 'rails/test_help' 4 | 5 | class ActiveSupport::TestCase 6 | # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order. 7 | fixtures :all 8 | 9 | # Add more helper methods to be used by all tests here... 10 | end 11 | -------------------------------------------------------------------------------- /bin/yarn: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | APP_ROOT = File.expand_path('..', __dir__) 3 | Dir.chdir(APP_ROOT) do 4 | begin 5 | exec "yarnpkg", *ARGV 6 | rescue Errno::ENOENT 7 | $stderr.puts "Yarn executable was not detected in the system." 8 | $stderr.puts "Download Yarn at https://yarnpkg.com/en/docs/install" 9 | exit 1 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /db/migrate/20190321070416_rename_attributes_db_connections.rb: -------------------------------------------------------------------------------- 1 | class RenameAttributesDbConnections < ActiveRecord::Migration[5.2] 2 | def change 3 | rename_column :db_connections, :iv, :initialization_vector 4 | rename_column :db_connections, :init_db, :initial_db 5 | rename_column :db_connections, :init_schema, :initial_schema 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /app/javascript/api/og_meta.ts: -------------------------------------------------------------------------------- 1 | import api from './base'; 2 | import { AxiosPromise } from 'axios'; 3 | 4 | export interface OGMeta { 5 | image?: string; 6 | title?: string; 7 | description?: string; 8 | site_name?: string; 9 | } 10 | 11 | export function getOGMeta(url: string): AxiosPromise { 12 | return api.post('og_meta', { url }); 13 | } -------------------------------------------------------------------------------- /app/api/entities/query_result.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Entities 4 | class QueryResult < Grape::Entity 5 | with_options(expose_nil: false) do 6 | expose :result 7 | expose :limit_reached 8 | expose :error 9 | expose :time 10 | expose :state 11 | expose :query_id 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /config/webpack/environment.js: -------------------------------------------------------------------------------- 1 | const { environment } = require('@rails/webpacker') 2 | 3 | environment.loaders.append('typescript', { 4 | test: /\.tsx?$/, 5 | exclude: /node_modules/, 6 | loader: 'awesome-typescript-loader' 7 | }); 8 | 9 | environment.loaders.append('css', 10 | { 11 | test: /\.css/, 12 | loader: 'style-loader!css-loader' 13 | }); 14 | 15 | module.exports = environment 16 | -------------------------------------------------------------------------------- /app/assets/stylesheets/application.scss: -------------------------------------------------------------------------------- 1 | @import "custom"; 2 | @import "sql_results"; 3 | @import "temp_db_server"; 4 | @import "database_schema_tree"; 5 | @import "query"; 6 | @import "db_server_card"; 7 | @import "user_list"; 8 | @import "about"; 9 | @import "graph_word_cloud"; 10 | @import "graph_line"; 11 | @import "profile"; 12 | @import "dashboard"; 13 | @import "clickable-icon"; 14 | @import "result_table"; -------------------------------------------------------------------------------- /app/javascript/models/Results/MultiResult.ts: -------------------------------------------------------------------------------- 1 | import Result, { ResultType, TableData } from "../Result"; 2 | import { MultiQueryResult, ResultState } from "../../api/db_server"; 3 | 4 | 5 | 6 | export default class MultiResult extends Result { 7 | get type(): ResultType { 8 | return ResultType.Multi; 9 | } 10 | 11 | get tableData(): TableData { 12 | return this.data; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /db/migrate/20200613181612_add_keys_to_users.rb: -------------------------------------------------------------------------------- 1 | class AddKeysToUsers < ActiveRecord::Migration[6.0] 2 | def change 3 | add_column :users, :private_key_pem, :string 4 | add_column :users, :public_key_pem, :string 5 | # since the key pair can only be generated on login when creating a new user 6 | # all login tokens must be deleted for this migration 7 | LoginToken.all.destroy_all 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /app/seeders/seed_groups.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class SeedGroups 4 | def self.perform 5 | g = Group.create!( 6 | name: 'Sharing is caring', 7 | is_private: true 8 | ) 9 | key = Group.random_crypto_key 10 | User.all.each do |user| 11 | g.add_user( 12 | user: user, 13 | group_key: key, 14 | is_admin: true 15 | ) 16 | end 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /app/javascript/utils/colors.ts: -------------------------------------------------------------------------------- 1 | import _ from 'lodash'; 2 | export const SEMANTIC_HEX_COLORS = [ 3 | '#db2828', 4 | '#21ba45', 5 | '#2185d0', 6 | '#1b1c1d', 7 | '#e03997', 8 | '#6435c9', 9 | '#00b5ad', 10 | '#f2711c', 11 | '#b5cc18', 12 | '#fbbd08', 13 | '#a5673f', 14 | '#a333c8', 15 | '#767676' 16 | ]; 17 | 18 | export const randomColor = (): string => { 19 | return _.sample(SEMANTIC_HEX_COLORS)!; 20 | } 21 | -------------------------------------------------------------------------------- /app/assets/javascripts/cable.js: -------------------------------------------------------------------------------- 1 | // Action Cable provides the framework to deal with WebSockets in Rails. 2 | // You can generate new channels where WebSocket features live using the `rails generate channel` command. 3 | // 4 | //= require action_cable 5 | //= require_self 6 | //= require_tree ./channels 7 | 8 | (function() { 9 | this.App || (this.App = {}); 10 | 11 | App.cable = ActionCable.createConsumer(); 12 | 13 | }).call(this); 14 | -------------------------------------------------------------------------------- /db/seeds.rb: -------------------------------------------------------------------------------- 1 | # This file should contain all the record creation needed to seed the database with its default values. 2 | # The data can then be loaded with the rails db:seed command (or created alongside the database with db:setup). 3 | 4 | require 'active_support/core_ext/digest/uuid' 5 | 6 | return unless Rails.env == 'development' 7 | 8 | SeedUsers.perform 9 | SeedGroups.perform 10 | SeedDatabaseSchemaQueries.perform 11 | SeedDbServers.perform 12 | -------------------------------------------------------------------------------- /app/assets/stylesheets/db_server_card.scss: -------------------------------------------------------------------------------- 1 | .db-server-card { 2 | position: relative; 3 | margin: 0 !important; 4 | .query-count { 5 | position: absolute; 6 | top: 4px; 7 | right: 4px; 8 | border-radius: 8px; 9 | height: 2rem; 10 | width: min-content; 11 | min-width: 2rem; 12 | padding: 0 4px; 13 | background: #E0E1E2 none; 14 | text-align: center; 15 | line-height: 2rem; 16 | cursor: pointer; 17 | } 18 | } -------------------------------------------------------------------------------- /config/initializers/backtrace_silencers.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. 4 | # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } 5 | 6 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. 7 | # Rails.backtrace_cleaner.remove_silencers! 8 | -------------------------------------------------------------------------------- /app/api/entities/rails_index.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Entities 4 | class RailsIndex < Grape::Entity 5 | expose :table 6 | expose :name 7 | expose :unique 8 | expose :columns 9 | expose :using 10 | expose :lengths 11 | expose :orders 12 | expose :opclasses 13 | with_options(expose_nil: false) do 14 | expose :where 15 | expose :type 16 | expose :comment 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /app/assets/stylesheets/query.scss: -------------------------------------------------------------------------------- 1 | .query-bar { 2 | display: flex; 3 | flex-direction: row; 4 | justify-content: space-between; 5 | align-items: center; 6 | .spacer { 7 | flex-grow: 1; 8 | flex-shrink: 1; 9 | flex-basis: 0; 10 | } 11 | .toggle.checkbox { 12 | margin-right: 1em; 13 | } 14 | } 15 | 16 | .ace_editor, 17 | .ace_editor div { 18 | font-family: Monaco, Menlo, 'Ubuntu Mono', Consolas, source-code-pro, monospace; 19 | } 20 | -------------------------------------------------------------------------------- /app/javascript/components/Workbench/SqlResult/EmptyResult.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Message } from 'semantic-ui-react'; 3 | import _ from 'lodash'; 4 | 5 | interface Props { 6 | queryIndex: number; 7 | } 8 | 9 | export const EmptyResult = ({ queryIndex }: Props) => { 10 | return ( 11 | 12 | {`Successfully executed query ${queryIndex + 1}.`} 13 | 14 | ); 15 | }; 16 | -------------------------------------------------------------------------------- /app/javascript/components/Workbench/SqlResult/SkippedResult.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Message } from 'semantic-ui-react'; 3 | import _ from 'lodash'; 4 | 5 | interface Props { 6 | queryIndex: number; 7 | } 8 | 9 | export const SkippedResult = ({ queryIndex }: Props) => { 10 | return ( 11 | 12 | {`Skipped query ${queryIndex + 1}.`} 13 | 14 | ); 15 | }; 16 | -------------------------------------------------------------------------------- /app/assets/stylesheets/result_table.scss: -------------------------------------------------------------------------------- 1 | @import "colors"; 2 | .ui.comments.img-comments { 3 | position: inherit; 4 | .comment { 5 | position: inherit; 6 | .avatar.comment-avatar-mini { 7 | width: 4.5em; 8 | border: 1px solid var(--highlight-grey-50); 9 | margin-right: 8px; 10 | border-radius: 8px; 11 | img { 12 | border-radius: 8px; 13 | } 14 | } 15 | 16 | .metadata.comment-metadata { 17 | margin-left: 0; 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /app/javascript/components/Workbench/SqlResult/ErrorReport.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Message } from 'semantic-ui-react'; 3 | import _ from 'lodash'; 4 | 5 | interface Props { 6 | queryIndex: number; 7 | error: string; 8 | } 9 | 10 | export const ErrorReport = ({ error, queryIndex }: Props) => { 11 | return ( 12 | 13 | {`Error in the ${queryIndex + 1}. query`} 14 |

{error}

15 |
16 | ); 17 | }; 18 | -------------------------------------------------------------------------------- /app/views/layouts/application.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | DbSql 5 | <%= csrf_meta_tags %> 6 | <%= stylesheet_link_tag 'application', media: 'all' %> 7 | <%= stylesheet_link_tag 'semantic', media: 'all' %> 8 | 9 | 10 | 11 | 12 | <%= yield %> 13 | <%= javascript_pack_tag 'App' %> 14 | 15 | 16 | -------------------------------------------------------------------------------- /app/api/entities/sql_query.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Entities 4 | class SqlQuery < Grape::Entity 5 | with_options(expose_nil: false) do 6 | expose :id 7 | expose :user_id 8 | expose :db_server_id 9 | expose :db_name 10 | expose :error 11 | expose :query 12 | expose :exec_time 13 | expose :is_private 14 | expose :is_favorite 15 | expose :is_valid 16 | expose :created_at 17 | expose :updated_at 18 | end 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /bin/webpack: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development" 4 | ENV["NODE_ENV"] ||= "development" 5 | 6 | require "pathname" 7 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 8 | Pathname.new(__FILE__).realpath) 9 | 10 | require "rubygems" 11 | require "bundler/setup" 12 | 13 | require "webpacker" 14 | require "webpacker/webpack_runner" 15 | 16 | APP_ROOT = File.expand_path("..", __dir__) 17 | Dir.chdir(APP_ROOT) do 18 | Webpacker::WebpackRunner.run(ARGV) 19 | end 20 | -------------------------------------------------------------------------------- /app/api/entities/rails_foreign_key.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Entities 4 | class RailsForeignKeyOptions < Grape::Entity 5 | with_options(expose_nil: false) do 6 | expose :column 7 | expose :name 8 | expose :primary_key 9 | expose :on_update 10 | expose :on_delete 11 | end 12 | end 13 | class RailsForeignKey < Grape::Entity 14 | expose :from_table 15 | expose :to_table 16 | expose :options, using: Entities::RailsForeignKeyOptions 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /bin/webpack-dev-server: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development" 4 | ENV["NODE_ENV"] ||= "development" 5 | 6 | require "pathname" 7 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 8 | Pathname.new(__FILE__).realpath) 9 | 10 | require "rubygems" 11 | require "bundler/setup" 12 | 13 | require "webpacker" 14 | require "webpacker/dev_server_runner" 15 | 16 | APP_ROOT = File.expand_path("..", __dir__) 17 | Dir.chdir(APP_ROOT) do 18 | Webpacker::DevServerRunner.run(ARGV) 19 | end 20 | -------------------------------------------------------------------------------- /app/javascript/antlr/QuerySeparationGrammar.g4: -------------------------------------------------------------------------------- 1 | grammar QuerySeparationGrammar; 2 | 3 | queriesText 4 | : statement* EOF 5 | ; 6 | 7 | statement 8 | : ';'* (CHAR | STRING | COMMENT)+ ';'* 9 | ; 10 | 11 | CHAR 12 | : ~';' 13 | ; 14 | 15 | STRING 16 | : '\'' ( ~'\'' | '\'\'' )* '\'' 17 | ; 18 | 19 | COMMENT 20 | : SIMPLE_COMMENT | BRACKETED_COMMENT 21 | ; 22 | 23 | fragment SIMPLE_COMMENT 24 | : '--' ~[\r\n]* '\r'? '\n'? 25 | ; 26 | 27 | fragment BRACKETED_COMMENT 28 | : '/*' .*? '*/' 29 | ; -------------------------------------------------------------------------------- /app/seeders/seed_users.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class SeedUsers 4 | def self.perform 5 | User.create!( 6 | email: 'test@user.ch', 7 | password: 'asdfasdf', 8 | password_confirmation: 'asdfasdf', 9 | role: 'admin', 10 | activated_at: DateTime.now - 2.days 11 | ) 12 | User.create!( 13 | email: 'admin@user.ch', 14 | password: 'asdfasdf', 15 | password_confirmation: 'asdfasdf', 16 | role: 'admin', 17 | activated_at: DateTime.now 18 | ) 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /db/migrate/20190512155558_add_foreign_key_constraint_to_active_storage_attachments_for_blob_id.active_storage.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from active_storage (originally 20180723000244) 2 | class AddForeignKeyConstraintToActiveStorageAttachmentsForBlobId < ActiveRecord::Migration[6.0] 3 | def up 4 | return if foreign_key_exists?(:active_storage_attachments, column: :blob_id) 5 | 6 | if table_exists?(:active_storage_blobs) 7 | add_foreign_key :active_storage_attachments, :active_storage_blobs, column: :blob_id 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /app/seeders/seed_database_schema_queries.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require_relative '../../lib/queries/query' 3 | 4 | class SeedDatabaseSchemaQueries 5 | def self.perform 6 | %i[psql mysql mariadb].each do |db_type| 7 | file = Rails.root.join(query_path(db_type: db_type), 'database_schema.sql') 8 | DatabaseSchemaQuery.create!( 9 | name: db_type.upcase, 10 | db_type: db_type, 11 | is_default: true, 12 | author: User.first, 13 | query: File.read(file) 14 | ) 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /config/initializers/cors.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Avoid CORS issues when API is called from the frontend app. 4 | # Handle Cross-Origin Resource Sharing (CORS) in order to accept cross-origin AJAX requests. 5 | 6 | # Read more: https://github.com/cyu/rack-cors 7 | 8 | Rails.application.config.middleware.insert_before 0, Rack::Cors do 9 | allow do 10 | origins '*' 11 | 12 | resource '*', 13 | headers: :any, 14 | methods: [:get, :post, :put, :patch, :delete, :options, :head] 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /config/initializers/wrap_parameters.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # This file contains settings for ActionController::ParamsWrapper which 4 | # is enabled by default. 5 | 6 | # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. 7 | ActiveSupport.on_load(:action_controller) do 8 | wrap_parameters format: [:json] 9 | end 10 | 11 | # To enable root element in JSON for ActiveRecord objects. 12 | # ActiveSupport.on_load(:active_record) do 13 | # self.include_root_in_json = true 14 | # end 15 | -------------------------------------------------------------------------------- /app/assets/stylesheets/temp_db_server.scss: -------------------------------------------------------------------------------- 1 | #host-port-group { 2 | display: flex; 3 | flex-direction: row; 4 | justify-content: space-between; 5 | 6 | .host { 7 | flex-grow: 1; 8 | margin-right: 1.5em; 9 | } 10 | } 11 | #db-connection-modal { 12 | .schema-query { 13 | display: flex; 14 | align-items: flex-end; 15 | .selection { 16 | flex-basis: 220px; 17 | margin-right: 4px; 18 | flex-grow: 0; 19 | flex-shrink: 1; 20 | } 21 | .editor { 22 | flex-grow: 1; 23 | flex-shrink: 1; 24 | flex-basis: 300px; 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /app/javascript/components/Navigation/Logout.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { inject } from 'mobx-react'; 3 | import SessionStore from '../../stores/session_store'; 4 | import { Button } from 'semantic-ui-react'; 5 | 6 | interface InjectedProps { 7 | sessionStore: SessionStore; 8 | } 9 | 10 | @inject('sessionStore') 11 | export default class LogoutButton extends React.Component { 12 | get injected() { 13 | return this.props as InjectedProps; 14 | } 15 | render() { 16 | return