From f90b557bfbc51e446841c27269a061327b27bb6c Mon Sep 17 00:00:00 2001 From: Peter Staab Date: Sat, 24 Feb 2024 07:22:01 -0500 Subject: [PATCH] Move database and external program settings This moves database and external program settings to webwork2.mojolicious.yml, moves code from database.conf.dist to WeBWorK::DB::Utils and load these settings into the CourseEnvironment. --- conf/README.md | 4 +- conf/database.conf.dist | 340 ----------------------------- conf/defaults.config | 45 +--- conf/site.conf.dist | 160 +------------- conf/webwork2.mojolicious.dist.yml | 87 ++++++++ lib/WeBWorK/CourseEnvironment.pm | 55 +++++ lib/WeBWorK/DB/Utils.pm | 272 +++++++++++++++++++++++ 7 files changed, 419 insertions(+), 544 deletions(-) delete mode 100644 conf/database.conf.dist diff --git a/conf/README.md b/conf/README.md index 4ef53a321d..aeaeebfb4e 100644 --- a/conf/README.md +++ b/conf/README.md @@ -16,8 +16,6 @@ Basic webwork2 configuration files. - `localOverrides.conf.dist` should be copied to `localOverrides.conf`. `localOverrides.conf` will be read after the `defaults.config` file is processed and will overwrite configurations in `defaults.config`. Use this file to make changes to the settings in `defaults.config`. -- `database.conf.dist` contains database configuration parameters. It is included by `defaults.config`. This file - should not be copied or modified unless you really know what you are doing. Configuration extension files. @@ -30,7 +28,7 @@ Configuration extension files. Server configuration files. - `webwork2.mojolicious.dist.yml` contains the webwork2 Mojolicious app configuration settings. Copy this file to - `webwork2.mojolicious.yml` if you need to change those settings. You usually will need to do this. + `webwork2.mojolicious.yml` if you need to change those settings. You usually will need to do this. This file contains server settings, database settings and paths to external programs. - `webwork2.dist.service` is a systemd configuration file for linux systems that serves the webwork2 app via the Mojolicious hypnotoad server. If you need to change it, then copy it to `webwork2.service`. - `webwork2-job-queue.dist.service` is a systemd configuration file for linux systems that runs the webwork2 job queue diff --git a/conf/database.conf.dist b/conf/database.conf.dist deleted file mode 100644 index 3b13b4e393..0000000000 --- a/conf/database.conf.dist +++ /dev/null @@ -1,340 +0,0 @@ -#!perl -################################################################################ -# WeBWorK Online Homework Delivery System -# Copyright © 2000-2023 The WeBWorK Project, https://github.com/openwebwork -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of either: (a) the GNU General Public License as published by the -# Free Software Foundation; either version 2, or (at your option) any later -# version, or (b) the "Artistic License" which comes with this package. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See either the GNU General Public License or the -# Artistic License for more details. -################################################################################ - -=head1 NAME - -database.conf - define standard database layouts - -=head1 SYNOPSIS - -In defaults.config: - - include "conf/database.conf"; - *dbLayout = $dbLayouts{layoutName}; - -=head1 DESCRIPTION - -This file contains definitions for the commonly-used database layouts. Database -layouts consist of all the information necessary to describe how to access data -used by WeBWorK. For more information on the format of a database layout, -consult the documentation for the WeBWorK::DB module. - -A database layout is selected from the list of possible layouts by adding a -line like the one below to the F or F file. - - $dbLayoutName = "layoutName"; - *dbLayout = $dbLayouts{$dbLayoutName}; - -=head2 THE SQL_SINGLE DATABASE LAYOUT - -The C layout is similar to the C layout, except that it uses a -single database for all courses. This is accomplished by prefixing each table -name with the name of the course. The names and passwords of these accounts are -given as parameters to each table in the layout. - - username the username to use when connecting to the database - password the password to use when connecting to the database - -Be default, username is "webworkRead" and password is "". It is not recommended -that you use only a non-empty password to secure database access. Most RDBMSs -allow IP-based authorization as well. As the system administrator, IT IS YOUR -RESPONSIBILITY TO SECURE DATABASE ACCESS. - -Don't confuse the account information above with the accounts of the users of a -course. This is a system-wide account which allow WeBWorK to talk to the -database server. - -Other parameters that can be given are as follows: - - tableOverride an alternate name to use when referring to the table (used - when a table name is a reserved word) - debug if true, SQL statements are printed before being executed - -=cut - -# params common to all tables - -my %sqlParams = ( - username => $database_username, - password => $database_password, - debug => $database_debug, - # kinda hacky, but needed for table dumping - mysql_path => $externalPrograms{mysql}, - mysqldump_path => $externalPrograms{mysqldump}, -); - -if ($ce->{database_driver} =~ /^mysql$/i) { - # The extra UTF8 connection setting is ONLY needed for older DBD:mysql driver - # and forbidden by the newer DBD::MariaDB driver - if ($ENABLE_UTF8MB4) { - $sqlParams{mysql_enable_utf8mb4} = 1; # Full 4-bit UTF-8 - } else { - $sqlParams{mysql_enable_utf8} = 1; # Only the partial 3-bit mySQL UTF-8 - } -} - -%dbLayouts = (); # layouts are added to this hash below - -$dbLayouts{sql_single} = { - locations => { - record => "WeBWorK::DB::Record::Locations", - schema => "WeBWorK::DB::Schema::NewSQL::Std", - driver => "WeBWorK::DB::Driver::SQL", - source => $database_dsn, - engine => $database_storage_engine, - character_set => $database_character_set, - params => { %sqlParams, non_native => 1 }, - }, - location_addresses => { - record => "WeBWorK::DB::Record::LocationAddresses", - schema => "WeBWorK::DB::Schema::NewSQL::Std", - driver => "WeBWorK::DB::Driver::SQL", - source => $database_dsn, - engine => $database_storage_engine, - character_set => $database_character_set, - params => { %sqlParams, non_native => 1 }, - }, - depths => { - record => "WeBWorK::DB::Record::Depths", - schema => "WeBWorK::DB::Schema::NewSQL::Std", - driver => "WeBWorK::DB::Driver::SQL", - source => $database_dsn, - engine => $database_storage_engine, - params => { %sqlParams, non_native => 1 }, - }, - password => { - record => "WeBWorK::DB::Record::Password", - schema => "WeBWorK::DB::Schema::NewSQL::Std", - driver => "WeBWorK::DB::Driver::SQL", - source => $database_dsn, - engine => $database_storage_engine, - character_set => $database_character_set, - params => { %sqlParams, tableOverride => "${courseName}_password" }, - }, - permission => { - record => "WeBWorK::DB::Record::PermissionLevel", - schema => "WeBWorK::DB::Schema::NewSQL::Std", - driver => "WeBWorK::DB::Driver::SQL", - source => $database_dsn, - engine => $database_storage_engine, - character_set => $database_character_set, - params => { %sqlParams, tableOverride => "${courseName}_permission" }, - }, - key => { - record => "WeBWorK::DB::Record::Key", - schema => "WeBWorK::DB::Schema::NewSQL::Std", - driver => "WeBWorK::DB::Driver::SQL", - source => $database_dsn, - engine => $database_storage_engine, - character_set => $database_character_set, - params => { %sqlParams, tableOverride => "${courseName}_key" }, - }, - user => { - record => "WeBWorK::DB::Record::User", - schema => "WeBWorK::DB::Schema::NewSQL::Std", - driver => "WeBWorK::DB::Driver::SQL", - source => $database_dsn, - engine => $database_storage_engine, - character_set => $database_character_set, - params => { %sqlParams, tableOverride => "${courseName}_user" }, - }, - set => { - record => "WeBWorK::DB::Record::Set", - schema => "WeBWorK::DB::Schema::NewSQL::Std", - driver => "WeBWorK::DB::Driver::SQL", - source => $database_dsn, - engine => $database_storage_engine, - character_set => $database_character_set, - params => { %sqlParams, tableOverride => "${courseName}_set" }, - }, - set_user => { - record => "WeBWorK::DB::Record::UserSet", - schema => "WeBWorK::DB::Schema::NewSQL::NonVersioned", - driver => "WeBWorK::DB::Driver::SQL", - source => $database_dsn, - engine => $database_storage_engine, - character_set => $database_character_set, - params => { %sqlParams, tableOverride => "${courseName}_set_user" }, - }, - set_merged => { - record => "WeBWorK::DB::Record::UserSet", - schema => "WeBWorK::DB::Schema::NewSQL::Merge", - driver => "WeBWorK::DB::Driver::SQL", - source => $database_dsn, - engine => $database_storage_engine, - character_set => $database_character_set, - depend => [qw/set_user set/], - params => { - %sqlParams, - non_native => 1, - merge => [qw/set_user set/], - }, - }, - set_version => { - record => "WeBWorK::DB::Record::SetVersion", - schema => "WeBWorK::DB::Schema::NewSQL::Versioned", - driver => "WeBWorK::DB::Driver::SQL", - source => $database_dsn, - engine => $database_storage_engine, - params => { - %sqlParams, - non_native => 1, - tableOverride => "${courseName}_set_user", - - }, - }, - set_version_merged => { - record => "WeBWorK::DB::Record::SetVersion", - schema => "WeBWorK::DB::Schema::NewSQL::Merge", - driver => "WeBWorK::DB::Driver::SQL", - source => $database_dsn, - engine => $database_storage_engine, - character_set => $database_character_set, - depend => [qw/set_version set_user set/], - params => { - %sqlParams, - non_native => 1, - merge => [qw/set_version set_user set/], - }, - }, - set_locations => { - record => "WeBWorK::DB::Record::SetLocations", - schema => "WeBWorK::DB::Schema::NewSQL::Std", - driver => "WeBWorK::DB::Driver::SQL", - source => $database_dsn, - engine => $database_storage_engine, - character_set => $database_character_set, - params => { %sqlParams, tableOverride => "${courseName}_set_locations" }, - }, - set_locations_user => { - record => "WeBWorK::DB::Record::UserSetLocations", - schema => "WeBWorK::DB::Schema::NewSQL::Std", - driver => "WeBWorK::DB::Driver::SQL", - source => $database_dsn, - engine => $database_storage_engine, - character_set => $database_character_set, - params => { %sqlParams, tableOverride => "${courseName}_set_locations_user" }, - }, - problem => { - record => "WeBWorK::DB::Record::Problem", - schema => "WeBWorK::DB::Schema::NewSQL::Std", - driver => "WeBWorK::DB::Driver::SQL", - source => $database_dsn, - engine => $database_storage_engine, - character_set => $database_character_set, - params => { %sqlParams, tableOverride => "${courseName}_problem" }, - }, - problem_user => { - record => "WeBWorK::DB::Record::UserProblem", - schema => "WeBWorK::DB::Schema::NewSQL::NonVersioned", - driver => "WeBWorK::DB::Driver::SQL", - source => $database_dsn, - engine => $database_storage_engine, - character_set => $database_character_set, - params => { %sqlParams, tableOverride => "${courseName}_problem_user" }, - }, - problem_merged => { - record => "WeBWorK::DB::Record::UserProblem", - schema => "WeBWorK::DB::Schema::NewSQL::Merge", - driver => "WeBWorK::DB::Driver::SQL", - source => $database_dsn, - engine => $database_storage_engine, - character_set => $database_character_set, - depend => [qw/problem_user problem/], - params => { - %sqlParams, - non_native => 1, - merge => [qw/problem_user problem/], - }, - }, - problem_version => { - record => "WeBWorK::DB::Record::ProblemVersion", - schema => "WeBWorK::DB::Schema::NewSQL::Versioned", - driver => "WeBWorK::DB::Driver::SQL", - source => $database_dsn, - engine => $database_storage_engine, - character_set => $database_character_set, - params => { - %sqlParams, - non_native => 1, - tableOverride => "${courseName}_problem_user", - }, - }, - problem_version_merged => { - record => "WeBWorK::DB::Record::ProblemVersion", - schema => "WeBWorK::DB::Schema::NewSQL::Merge", - driver => "WeBWorK::DB::Driver::SQL", - source => $database_dsn, - engine => $database_storage_engine, - character_set => $database_character_set, - depend => [qw/problem_version problem_user problem/], - params => { - %sqlParams, - non_native => 1, - merge => [qw/problem_version problem_user problem/], - }, - }, - setting => { - record => "WeBWorK::DB::Record::Setting", - schema => "WeBWorK::DB::Schema::NewSQL::Std", - driver => "WeBWorK::DB::Driver::SQL", - source => $database_dsn, - engine => $database_storage_engine, - character_set => $database_character_set, - params => { %sqlParams, tableOverride => "${courseName}_setting" }, - }, - achievement => { - record => "WeBWorK::DB::Record::Achievement", - schema => "WeBWorK::DB::Schema::NewSQL::Std", - driver => "WeBWorK::DB::Driver::SQL", - source => $database_dsn, - engine => $database_storage_engine, - character_set => $database_character_set, - params => { %sqlParams, tableOverride => "${courseName}_achievement" }, - }, - past_answer => { - record => "WeBWorK::DB::Record::PastAnswer", - schema => "WeBWorK::DB::Schema::NewSQL::Std", - driver => "WeBWorK::DB::Driver::SQL", - source => $database_dsn, - engine => $database_storage_engine, - character_set => $database_character_set, - params => { %sqlParams, tableOverride => "${courseName}_past_answer" }, - }, - - achievement_user => { - record => "WeBWorK::DB::Record::UserAchievement", - schema => "WeBWorK::DB::Schema::NewSQL::Std", - driver => "WeBWorK::DB::Driver::SQL", - source => $database_dsn, - engine => $database_storage_engine, - character_set => $database_character_set, - params => { %sqlParams, tableOverride => "${courseName}_achievement_user" }, - }, - global_user_achievement => { - record => "WeBWorK::DB::Record::GlobalUserAchievement", - schema => "WeBWorK::DB::Schema::NewSQL::Std", - driver => "WeBWorK::DB::Driver::SQL", - source => $database_dsn, - engine => $database_storage_engine, - character_set => $database_character_set, - params => { %sqlParams, tableOverride => "${courseName}_global_user_achievement" }, - }, -}; - -# include ("conf/database.conf"); # uncomment to provide local overrides - -1; diff --git a/conf/defaults.config b/conf/defaults.config index 84a57e7a87..4f58f0ddd7 100644 --- a/conf/defaults.config +++ b/conf/defaults.config @@ -585,37 +585,6 @@ $default_status = "Enrolled"; }, ); -################################################################################ -# Database options -################################################################################ - -# Database schemas are defined in the file conf/database.conf and stored in the -# hash %dbLayouts. The standard schema is called "sql_single"; - -include( "./conf/database.conf.dist"); # always include database.conf.dist - - # in the rare case where you want local overrides - # you can place include("conf/database.conf") in - # the database.conf.dist file -# this change is meant to help alleviate the common mistake of forgetting to update the -# database.conf file when changing WW versions. - -# Select the default database layout. This can be overridden in the course.conf -# file of a particular course. The only database layout supported in WW 2.1.4 -# and up is "sql_single". -$dbLayoutName = "sql_single"; - -# This sets the symbol "dbLayout" as an alias for the selected database layout. -*dbLayout = $dbLayouts{$dbLayoutName}; - -# This sets the max course id length. It might need to be changed depending -# on what database tables are present. Mysql allows a max table length of 64 -# characters. With the ${course_id}_global_user_achievement table that means -# the max ${course_id} is exactly 40 characters. - -$maxCourseIdLength = 40; - -# Reference: https://dev.mysql.com/doc/refman/8.0/en/identifier-length.html ################################################################################ # Problem library options @@ -636,13 +605,7 @@ $contribLibrary{root} = "/opt/webwork/libraries/webwork-open-problem-libra $problemLibrary{version} = "2.5"; ########################################################### -# Problem Library SQL database connection information -$problemLibrary_db = { - dbsource => $database_dsn, - user => $database_username, - passwd => $database_password, - storage_engine => 'MYISAM', -}; +# The database settings for the OPL is now set in CourseEnvironment. $problemLibrary{tree} = 'library-directory-tree.json'; @@ -1056,10 +1019,8 @@ $pg{displayModeOptions}{images} = { # If dbsource is set to a nonempty value, then this database connection information will be used to store dvipng # depths. It is assumed that the 'depths' table exists in the database. - dvipng_depth_db => { - dbsource => $database_dsn, - user => $database_username, - passwd => $database_password, + # These are set in the CourseEnvironment. + dvipng_depth_db => {} }, }; diff --git a/conf/site.conf.dist b/conf/site.conf.dist index a5cd8f23a9..b1e2725c02 100644 --- a/conf/site.conf.dist +++ b/conf/site.conf.dist @@ -93,165 +93,7 @@ $admin_course_id = 'admin'; # status. #$new_courses_hidden_status = 'hidden'; -# password strings (or any other string allowing special characters) should be specified inside single quotes -# otherwise a string such as "someone@nowhere" will interpolate the contents of the array @nowhere -- which is probably -# empty, but still not what you want. Similar things happen with % and $ -################################################################################ -# Paths to external programs -################################################################################ - -# These applications are often found in /bin, but sometimes in /usr/bin -# or even in /opt/local/bin. -# You can use "which tar" for example to find out where the "tar" program is located - -#################################################### -# system utilities -#################################################### -$externalPrograms{tar} = "/bin/tar"; -$externalPrograms{git} = "/usr/bin/git"; - - -#################################################### -# equation rendering/hardcopy utiltiies -#################################################### -$externalPrograms{latex} = "/usr/bin/latex --no-shell-escape"; - -$externalPrograms{pdflatex} = "/usr/bin/pdflatex --no-shell-escape"; -# Note that --no-shell-escape is important for security reasons. -# Consider using xelatex instead of pdflatex for multilingual use, and -# use polyglossia and fontspec packages (which require xelatex or lualatex). -#$externalPrograms{pdflatex} = "/usr/bin/xelatex --no-shell-escape"; - -$externalPrograms{dvipng} = "/usr/bin/dvipng"; - -# In order to use imagemagick convert you need to change the rights for PDF files from -# "none" to "read" in the policy file /etc/ImageMagick-6/policy.xml. This has possible -# security implications for the server. -$externalPrograms{convert} = "/usr/bin/convert"; - -$externalPrograms{dvisvgm} = "/usr/bin/dvisvgm"; -$externalPrograms{pdf2svg} = "/usr/bin/pdf2svg"; - -#################################################### -# NetPBM - basic image manipulation utilities -# Most sites only need to configure $netpbm_prefix. -#################################################### -my $netpbm_prefix = "/usr/bin"; -$externalPrograms{giftopnm} = "$netpbm_prefix/giftopnm"; -$externalPrograms{ppmtopgm} = "$netpbm_prefix/ppmtopgm"; -$externalPrograms{pnmtops} = "$netpbm_prefix/pnmtops"; -$externalPrograms{pnmtopng} = "$netpbm_prefix/pnmtopng"; -$externalPrograms{pngtopnm} = "$netpbm_prefix/pngtopnm"; - -#################################################### -# curl -#################################################### -$externalPrograms{curl} = "/usr/bin/curl"; - -#################################################### -# image conversions utiltiies -# the source file is given on stdin, and the output expected on stdout. -#################################################### - -$externalPrograms{gif2eps} = "$externalPrograms{giftopnm} | $externalPrograms{ppmtopgm} | $externalPrograms{pnmtops} -noturn 2>/dev/null"; -$externalPrograms{png2eps} = "$externalPrograms{pngtopnm} | $externalPrograms{ppmtopgm} | $externalPrograms{pnmtops} -noturn 2>/dev/null"; -$externalPrograms{gif2png} = "$externalPrograms{giftopnm} | $externalPrograms{pnmtopng}"; - -#################################################### -# mysql clients -#################################################### - -$externalPrograms{mysql} ="/usr/bin/mysql"; -$externalPrograms{mysqldump} ="/usr/bin/mysqldump"; - - -#################################################### -# End paths to external utilities. -#################################################### - -################################################################################ -# Database options -################################################################################ - -# $database_debug = 0; - -# Standard permissions command used to initialize the webwork database -# GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, DROP, INDEX, LOCK TABLES ON webwork.* TO webworkWrite@localhost IDENTIFIED BY 'passwordRW'; -# where webworkWrite and passwordRW must match the corresponding variables in the next section. - -################################################################################ -# these variables are used by database.conf. we define them here so that editing -# database.conf isn't necessary. - -# You must initialize the database and set the password for webworkWrite. -# Edit the $database_password line and replace 'passwordRW' by the actual password used in the GRANT command above -################################################################################ - -# The database DSN is the path to the WeBWorK database which you have created. - -# Modern database DSN format: -# DBI:driver:database=$database;host=$hostname;port=$port (when DB not on localhost) -# or DBI:driver:database=$database;host=127.0.0.1;port=$port (when DB on localhost, using TCP) -# See: https://metacpan.org/pod/DBD::MariaDB#port -# "To connect to a MariaDB or MySQL server on localhost using TCP/IP, -# you must specify the host as 127.0.0.1 with the optional port, e.g. 3306." -# or DBI:driver:database=$database (when DB on localhost, using socket) - -# One thing on which it depends is the driver name, which you may want to modify. -# It also depends on the database name, which may be non-standard in some settings, -# as may be the hostname and port of the database server. - -# driver should be one of: -# "mysql" for the DBD:mysql driver -# "MariaDB" for the DBD:mysql driver - -# Select the desired DB driver: -#$database_driver="mysql"; -$database_driver="MariaDB"; - -$database_host="localhost"; -$database_port="3306"; -$database_name="webwork"; - -# For a DB on localhost - default to using Unix socket. -# Change to 0 to use a TCP connection to 127.0.0.1. -$database_use_socket_if_localhost=1; - -if ( $database_host eq "localhost" ) { - if ( $database_use_socket_if_localhost ) { - $database_dsn="DBI:$database_driver:database=$database_name"; - } else { - $database_dsn="DBI:$database_driver:database=$database_name;host=127.0.0.1;port=$database_port"; - } -} else { - $database_dsn="DBI:$database_driver:database=$database_name;host=$database_host;port=$database_port"; -} - -# The default storange engine to use is set here: -$database_storage_engine = 'myisam'; - -######################### -# MYSQL compatibility settings for handling international Unicode characters (utf8 and utf8mb) -######################### -# These set the way characters are encoded in mysql and will depend on the version of mysqld being used. -# the default is to use latin1. With version 2.15 we will move to -# encoding utf8mb4 which allows the encoding of characters from many languages -# including chinese, arabic and hebrew. - -$ENABLE_UTF8MB4 =1; # setting this to 1 enables utf8mb4 encoding, setting this to - # 0 sets this for older mysql (pre 5.3) which cannot - # handle utf8mb4 characters. - -$database_character_set=($ENABLE_UTF8MB4) ? 'utf8mb4' : 'utf8'; - - -# DATABASE login information -# The following two variables must match the GRANT statement run on the mysql server as described above. -$database_username ="webworkWrite"; -$database_password ='passwordRW'; -# password strings (or any other string allowing special characters) should be specified inside single quotes -# otherwise a string such as "someone@nowhere" will interpolate the contents of the array @nowhere -- which is probably -# empty, but still not what you want. Similar things happen with % and $ +# External Programs and database settings are now defined in webwork2.mojolicious.yml ################################################################################# # These variables describe the locations of various components of WeBWorK on your diff --git a/conf/webwork2.mojolicious.dist.yml b/conf/webwork2.mojolicious.dist.yml index cb4397297e..b715857b79 100644 --- a/conf/webwork2.mojolicious.dist.yml +++ b/conf/webwork2.mojolicious.dist.yml @@ -239,3 +239,90 @@ debug: hardcopy: # If 1, don't delete temporary files created when a hardcopy is generated. preserve_temp_files: 0 + +# External Programs + +# These applications are often found in /bin, but sometimes in /usr/bin or even in /opt/local/bin. +# You can use "which tar" for example to find out where the "tar" program is located + +externalPrograms: + mv: /bin/mv + cp: /bin/cp + rm: /bin/rm + mkdir: /bin/mkdir + tar: /bin/tar + gzip: /bin/gzip + git: /bin/git + curl: /usr/bin/curl + mysql: /usr/bin/mysql + mysqldump: /usr/bin/mysqldump + + # latex and related utilities + latex: /usr/bin/latex --no-shell-escape + pdflatex: /usr/bin/pdflatex --no-shell-escape + + # Note that --no-shell-escape is important for security reasons. + # Consider using xelatex instead of pdflatex for multilingual use, and + # use polyglossia and fontspec packages (which require xelatex or lualatex). + # pdflatex: /usr/bin/xelatex --no-shell-escape + + dvipng: /usr/bin/dvipng + convert: /usr/bin/convert + dvisvgm: /usr/bin/dvisvgm + pdf2svg: /usr/bin/pdf2svg + + giftopnm: /usr/bin/giftopnm + ppmtopgm: /usr/bin/ppmtopgm + pnmtops: /usr/bin/pnmtops + pnmtopng: /usr/bin/pnmtopng + pnmtopnm: /usr/bin/pnmtopnm + +# Database options + +database: + # uncomment to allow database debug information + # debug: 1 + + # Select the desired DB driver: either 'mysql' or 'MariaDB' + # database_driver: mysql + driver: MariaDB + + host: localhost + port: 3306 + + # name of the database + name: webwork + + # Standard permissions command used to initialize the webwork database + # GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, DROP, INDEX, LOCK TABLES ON webwork.* TO webworkWrite@localhost IDENTIFIED BY 'passwordRW'; + # where webworkWrite and passwordRW must match the corresponding variables in the next section. + username: '' + password: '' + + # For a DB on localhost - default to using Unix socket. Change to 0 to use a TCP connection to 127.0.0.1. + use_socket_if_localhost: 1 + + # Need to add the code in lines 209-217 to a perl file + # Add line 234 to same file + + # The default storange engine to use is set here: + storage_engine: myisam + + # MYSQL compatibility settings for handling international Unicode characters (utf8 and utf8mb) + + # These set the way characters are encoded in mysql and will depend on the version of mysqld being used. + # the default is to use latin1. With version 2.15 we will move to encoding utf8mb4 which allows + # the encoding of characters from many languages including chinese, arabic and hebrew. + + # setting this to 1 enables utf8mb4 encoding, setting this to 0 sets this for older + # mysql (pre 5.3) which cannot handle utf8mb4 characters. + + ENABLE_UTF8MB4: 1 + + # This sets the max course id length. It might need to be changed depending + # on what database tables are present. Mysql allows a max table length of 64 + # characters. With the ${course_id}_global_user_achievement table that means + # the max ${course_id} is exactly 40 characters. + + # Reference: https://dev.mysql.com/doc/refman/8.0/en/identifier-length.html + maxCourseIdLength: 40 diff --git a/lib/WeBWorK/CourseEnvironment.pm b/lib/WeBWorK/CourseEnvironment.pm index 98d977ddb9..703cf96745 100644 --- a/lib/WeBWorK/CourseEnvironment.pm +++ b/lib/WeBWorK/CourseEnvironment.pm @@ -54,10 +54,12 @@ use warnings; use Carp; use Opcode qw(empty_opset); +use YAML::XS qw(LoadFile); use WeBWorK::WWSafe; use WeBWorK::Utils qw(readFile); use WeBWorK::Debug; +use WeBWorK::DB::Utils qw(databaseParams); =head1 CONSTRUCTION @@ -246,6 +248,17 @@ sub new { $self->{language} = 'zh-HK' if $self->{language} eq 'zh-hk'; $self->{language} = 'en' if $self->{language} eq 'en-us'; + # Load additional configuration variables. + my $defaults_file = "$seedVars->{webwork_dir}/conf/webwork2.mojolicious.dist.yml"; + die "Cannot read the mojolicous defaults file: $defaults_file" unless -r $defaults_file; + + # If this exists, load the overrides file (replacement for local overrides): + my $config_file = "$seedVars->{webwork_dir}/conf/webwork2.mojolicious.yml"; + my $config = -r $config_file ? LoadFile($config_file) : LoadFile($defaults_file); + + # Set the database settings. + $self->set_server_settings($config); + # now that we're done, we can go ahead and return... return $self; } @@ -365,6 +378,48 @@ sub status_abbrev_has_behavior { } } +sub set_server_settings { + my ($ce, $config) = @_; + + # set the database settings: + $ce->{database_name} = $config->{database}{name}; + $ce->{database_host} = $config->{database}{host}; + $ce->{database_username} = $config->{database}{username}; + $ce->{database_password} = $config->{database}{password}; + if ($config->{database}{host} eq "localhost") { + $ce->{database_dsn} = + $config->{database}{use_socket_if_localhost} + ? "DBI:$config->{database}{driver}:database=$config->{database}{name}" + : "DBI:$config->{database}{driver}:database=$config->{database}{name};" + . "host=127.0.0.1;port=$config->{database}{port}"; + } else { + $ce->{database_dsn} = "DBI:$config->{database}{driver}:database=$config->{database}{name};" + . "host=$config->{database}{host};port=$config->{database}{port}"; + } + $ce->{dbLayoutName} = 'sql_single'; + $config->{database}{dsn} = $ce->{database_dsn}; + $config->{database}{character_set} = $config->{database}{ENABLE_UTF8MB4} ? 'utf8mb4' : 'utf8'; + $ce->{dbLayout} = databaseParams($ce->{courseName}, $config->{database}, $config->{externalPrograms}); + + $ce->{maxCourseIdLength} = $config->{database}{maxCourseIdLength}; + + # ensure that the dvipng_depth_db information is defined: + $ce->{pg}{displayModeOptions}{images}{dvipng_depth_db}{user} //= $config->{database}{username}; + $ce->{pg}{displayModeOptions}{images}{dvipng_depth_db}{passwd} //= $config->{database}{password}; + $ce->{pg}{displayModeOptions}{images}{dvipng_depth_db}{dbsource} //= $ce->{database_dsn}; + + # Problem Library SQL database connection information + $c->{problemLibrary_db} = { + dbsource => $ce->{database_dsn}, + user => $ce->{database_username}, + passwd => $ce->{database_password}, + storage_engine => 'MYISAM', + }; + + $ce->{externalPrograms} = $config->{externalPrograms}; + return; +} + =back =cut diff --git a/lib/WeBWorK/DB/Utils.pm b/lib/WeBWorK/DB/Utils.pm index 2a6476c0c7..e467e64088 100644 --- a/lib/WeBWorK/DB/Utils.pm +++ b/lib/WeBWorK/DB/Utils.pm @@ -35,6 +35,7 @@ our @EXPORT_OK = qw( grok_vsetID grok_setID_from_vsetID_sql grok_versionID_from_vsetID_sql + databaseParams ); sub global2user($$) { @@ -108,4 +109,275 @@ sub grok_versionID_from_vsetID_sql($) { return "(SUBSTRING($field,INSTR($field,',v')+2)+0)"; } +# This function fills database fields of the CourseEnvironment + +sub databaseParams { + my ($courseName, $db_params, $externalPrograms) = @_; + + my %sqlParams = ( + username => $db_params->{username}, + password => $db_params->{password}, + debug => $db_params->{database_debug} // 0, + # kinda hacky, but needed for table dumping + mysql_path => $externalPrograms->{mysql}, + mysqldump_path => $externalPrograms->{mysqldump}, + ); + + if ($db_params->{driver} =~ /^mysql$/i) { + # The extra UTF8 connection setting is ONLY needed for older DBD:mysql driver + # and forbidden by the newer DBD::MariaDB driver + if ($db_params->{ENABLE_UTF8MB4}) { + $sqlParams{mysql_enable_utf8mb4} = 1; # Full 4-bit UTF-8 + } else { + $sqlParams{mysql_enable_utf8} = 1; # Only the partial 3-bit mySQL UTF-8 + } + } + return { + locations => { + record => "WeBWorK::DB::Record::Locations", + schema => "WeBWorK::DB::Schema::NewSQL::Std", + driver => "WeBWorK::DB::Driver::SQL", + source => $db_params->{dsn}, + engine => $db_params->{storage_engine}, + character_set => $db_params->{character_set}, + params => { %sqlParams, non_native => 1 }, + }, + location_addresses => { + record => "WeBWorK::DB::Record::LocationAddresses", + schema => "WeBWorK::DB::Schema::NewSQL::Std", + driver => "WeBWorK::DB::Driver::SQL", + source => $db_params->{dsn}, + engine => $db_params->{storage_engine}, + character_set => $db_params->{character_set}, + params => { %sqlParams, non_native => 1 }, + }, + depths => { + record => "WeBWorK::DB::Record::Depths", + schema => "WeBWorK::DB::Schema::NewSQL::Std", + driver => "WeBWorK::DB::Driver::SQL", + source => $db_params->{dsn}, + engine => $db_params->{storage_engine}, + params => { %sqlParams, non_native => 1 }, + }, + password => { + record => "WeBWorK::DB::Record::Password", + schema => "WeBWorK::DB::Schema::NewSQL::Std", + driver => "WeBWorK::DB::Driver::SQL", + source => $db_params->{dsn}, + engine => $db_params->{storage_engine}, + character_set => $db_params->{character_set}, + params => { %sqlParams, tableOverride => "${courseName}_password" }, + }, + permission => { + record => "WeBWorK::DB::Record::PermissionLevel", + schema => "WeBWorK::DB::Schema::NewSQL::Std", + driver => "WeBWorK::DB::Driver::SQL", + source => $db_params->{dsn}, + engine => $db_params->{storage_engine}, + character_set => $db_params->{character_set}, + params => { %sqlParams, tableOverride => "${courseName}_permission" }, + }, + key => { + record => "WeBWorK::DB::Record::Key", + schema => "WeBWorK::DB::Schema::NewSQL::Std", + driver => "WeBWorK::DB::Driver::SQL", + source => $db_params->{dsn}, + engine => $db_params->{storage_engine}, + character_set => $db_params->{character_set}, + params => { %sqlParams, tableOverride => "${courseName}_key" }, + }, + user => { + record => "WeBWorK::DB::Record::User", + schema => "WeBWorK::DB::Schema::NewSQL::Std", + driver => "WeBWorK::DB::Driver::SQL", + source => $db_params->{dsn}, + engine => $db_params->{storage_engine}, + character_set => $db_params->{character_set}, + params => { %sqlParams, tableOverride => "${courseName}_user" }, + }, + set => { + record => "WeBWorK::DB::Record::Set", + schema => "WeBWorK::DB::Schema::NewSQL::Std", + driver => "WeBWorK::DB::Driver::SQL", + source => $db_params->{dsn}, + engine => $db_params->{storage_engine}, + character_set => $db_params->{character_set}, + params => { %sqlParams, tableOverride => "${courseName}_set" }, + }, + set_user => { + record => "WeBWorK::DB::Record::UserSet", + schema => "WeBWorK::DB::Schema::NewSQL::NonVersioned", + driver => "WeBWorK::DB::Driver::SQL", + source => $db_params->{dsn}, + engine => $db_params->{storage_engine}, + character_set => $db_params->{character_set}, + params => { %sqlParams, tableOverride => "${courseName}_set_user" }, + }, + set_merged => { + record => "WeBWorK::DB::Record::UserSet", + schema => "WeBWorK::DB::Schema::NewSQL::Merge", + driver => "WeBWorK::DB::Driver::SQL", + source => $db_params->{dsn}, + engine => $db_params->{storage_engine}, + character_set => $db_params->{character_set}, + depend => [qw/set_user set/], + params => { + %sqlParams, + non_native => 1, + merge => [qw/set_user set/], + }, + }, + set_version => { + record => "WeBWorK::DB::Record::SetVersion", + schema => "WeBWorK::DB::Schema::NewSQL::Versioned", + driver => "WeBWorK::DB::Driver::SQL", + source => $db_params->{dsn}, + engine => $db_params->{storage_engine}, + params => { + %sqlParams, + non_native => 1, + tableOverride => "${courseName}_set_user", + + }, + }, + set_version_merged => { + record => "WeBWorK::DB::Record::SetVersion", + schema => "WeBWorK::DB::Schema::NewSQL::Merge", + driver => "WeBWorK::DB::Driver::SQL", + source => $db_params->{dsn}, + engine => $db_params->{storage_engine}, + character_set => $db_params->{character_set}, + depend => [qw/set_version set_user set/], + params => { + %sqlParams, + non_native => 1, + merge => [qw/set_version set_user set/], + }, + }, + set_locations => { + record => "WeBWorK::DB::Record::SetLocations", + schema => "WeBWorK::DB::Schema::NewSQL::Std", + driver => "WeBWorK::DB::Driver::SQL", + source => $db_params->{dsn}, + engine => $db_params->{storage_engine}, + character_set => $db_params->{character_set}, + params => { %sqlParams, tableOverride => "${courseName}_set_locations" }, + }, + set_locations_user => { + record => "WeBWorK::DB::Record::UserSetLocations", + schema => "WeBWorK::DB::Schema::NewSQL::Std", + driver => "WeBWorK::DB::Driver::SQL", + source => $db_params->{dsn}, + engine => $db_params->{storage_engine}, + character_set => $db_params->{character_set}, + params => { %sqlParams, tableOverride => "${courseName}_set_locations_user" }, + }, + problem => { + record => "WeBWorK::DB::Record::Problem", + schema => "WeBWorK::DB::Schema::NewSQL::Std", + driver => "WeBWorK::DB::Driver::SQL", + source => $db_params->{dsn}, + engine => $db_params->{storage_engine}, + character_set => $db_params->{character_set}, + params => { %sqlParams, tableOverride => "${courseName}_problem" }, + }, + problem_user => { + record => "WeBWorK::DB::Record::UserProblem", + schema => "WeBWorK::DB::Schema::NewSQL::NonVersioned", + driver => "WeBWorK::DB::Driver::SQL", + source => $db_params->{dsn}, + engine => $db_params->{storage_engine}, + character_set => $db_params->{character_set}, + params => { %sqlParams, tableOverride => "${courseName}_problem_user" }, + }, + problem_merged => { + record => "WeBWorK::DB::Record::UserProblem", + schema => "WeBWorK::DB::Schema::NewSQL::Merge", + driver => "WeBWorK::DB::Driver::SQL", + source => $db_params->{dsn}, + engine => $db_params->{storage_engine}, + character_set => $db_params->{character_set}, + depend => [qw/problem_user problem/], + params => { + %sqlParams, + non_native => 1, + merge => [qw/problem_user problem/], + }, + }, + problem_version => { + record => "WeBWorK::DB::Record::ProblemVersion", + schema => "WeBWorK::DB::Schema::NewSQL::Versioned", + driver => "WeBWorK::DB::Driver::SQL", + source => $db_params->{dsn}, + engine => $db_params->{storage_engine}, + character_set => $db_params->{character_set}, + params => { + %sqlParams, + non_native => 1, + tableOverride => "${courseName}_problem_user", + }, + }, + problem_version_merged => { + record => "WeBWorK::DB::Record::ProblemVersion", + schema => "WeBWorK::DB::Schema::NewSQL::Merge", + driver => "WeBWorK::DB::Driver::SQL", + source => $db_params->{dsn}, + engine => $db_params->{storage_engine}, + character_set => $db_params->{character_set}, + depend => [qw/problem_version problem_user problem/], + params => { + %sqlParams, + non_native => 1, + merge => [qw/problem_version problem_user problem/], + }, + }, + setting => { + record => "WeBWorK::DB::Record::Setting", + schema => "WeBWorK::DB::Schema::NewSQL::Std", + driver => "WeBWorK::DB::Driver::SQL", + source => $db_params->{dsn}, + engine => $db_params->{storage_engine}, + character_set => $db_params->{character_set}, + params => { %sqlParams, tableOverride => "${courseName}_setting" }, + }, + achievement => { + record => "WeBWorK::DB::Record::Achievement", + schema => "WeBWorK::DB::Schema::NewSQL::Std", + driver => "WeBWorK::DB::Driver::SQL", + source => $db_params->{dsn}, + engine => $db_params->{storage_engine}, + character_set => $db_params->{character_set}, + params => { %sqlParams, tableOverride => "${courseName}_achievement" }, + }, + past_answer => { + record => "WeBWorK::DB::Record::PastAnswer", + schema => "WeBWorK::DB::Schema::NewSQL::Std", + driver => "WeBWorK::DB::Driver::SQL", + source => $db_params->{dsn}, + engine => $db_params->{storage_engine}, + character_set => $db_params->{character_set}, + params => { %sqlParams, tableOverride => "${courseName}_past_answer" }, + }, + + achievement_user => { + record => "WeBWorK::DB::Record::UserAchievement", + schema => "WeBWorK::DB::Schema::NewSQL::Std", + driver => "WeBWorK::DB::Driver::SQL", + source => $db_params->{dsn}, + engine => $db_params->{storage_engine}, + character_set => $db_params->{character_set}, + params => { %sqlParams, tableOverride => "${courseName}_achievement_user" }, + }, + global_user_achievement => { + record => "WeBWorK::DB::Record::GlobalUserAchievement", + schema => "WeBWorK::DB::Schema::NewSQL::Std", + driver => "WeBWorK::DB::Driver::SQL", + source => $db_params->{dsn}, + engine => $db_params->{storage_engine}, + character_set => $db_params->{character_set}, + params => { %sqlParams, tableOverride => "${courseName}_global_user_achievement" }, + }, + }; +} + 1;