diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 56123e25..c0c6d603 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -17,9 +17,35 @@ jobs: - name: run tests run: go test -v ./... working-directory: ./server + test_migrations: + runs-on: ubuntu-latest + services: + mariadb: + image: bitnami/mariadb:latest + ports: + - 3306:3306 + env: + MARIADB_ROOT_PASSWORD: super_secret_passw0rd + MARIADB_DATABASE: campus_db + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v4 + with: + go-version: '1.21' + cache-dependency-path: | + server/go.sum + - name: wait for db + run: sleep 20 && docker logs $(docker ps -qa) + - name: run migration + run: go run main.go + working-directory: ./server + env: + CI_EXIT_AFTER_MIGRATION: "true" + DB_DSN: root:super_secret_passw0rd@tcp(localhost:3306)/campus_db?charset=utf8mb4&parseTime=True&loc=Local + ENVIRONMENT: dev build: runs-on: ubuntu-latest - needs: [test] + needs: [test, test_migrations] steps: - name: Checkout repository uses: actions/checkout@v4 diff --git a/README.md b/README.md index 350490e2..a1c4d7db 100644 --- a/README.md +++ b/README.md @@ -80,12 +80,6 @@ The docker compose will start the server and a mariadb instance. The server will be available at `localhost:50051` and the mariadb instance at `localhost:3306`. Additionally, docker creates the volume `campus-db-data` to persist the data of the mariadb instances. -### Setting up the Database -The mariadb schema can be installed by executing the following command inside the mariadb container: -```bash -mysql --user=root --password=secret_root_password campus_db < /entrypoint/schema.sql -``` - ### Environment Variables The following environment variables need to be set for the server to work properly: * [REQUIRED] `DB_NAME`: The name of the database to use. diff --git a/deployment/charts/backend/templates/sql-init-config.yaml b/deployment/charts/backend/templates/sql-init-config.yaml deleted file mode 100644 index 5183fe11..00000000 --- a/deployment/charts/backend/templates/sql-init-config.yaml +++ /dev/null @@ -1,8 +0,0 @@ -kind: ConfigMap -apiVersion: v1 -metadata: - name: sql-init - namespace: {{ $.Values.namespace }} -data: - schema.sql: |- -{{ .Files.Get "files/source-schema.sql" | indent 4 }} diff --git a/deployment/charts/backend/values.yaml b/deployment/charts/backend/values.yaml index 1d2fa341..9ac3673b 100644 --- a/deployment/charts/backend/values.yaml +++ b/deployment/charts/backend/values.yaml @@ -38,7 +38,6 @@ mariadb: storageClass: local-path volumePermissions: enabled: true - initdbScriptsConfigMap: sql-init backend: diff --git a/docker-compose.yaml b/docker-compose.yaml index 9bc5cc4a..e876f031 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -39,7 +39,6 @@ services: - MARIADB_DATABASE=${DB_NAME} volumes: - campus-db-data:/bitnami/mariadb - - ./deployment/charts/backend/files/source-schema.sql:/docker-entrypoint-startdb.d/schema.sql healthcheck: test: ['CMD', '/opt/bitnami/scripts/mariadb/healthcheck.sh'] interval: 15s diff --git a/server/backend/migration/20200000000000.go b/server/backend/migration/20200000000000.go new file mode 100644 index 00000000..3ed3e9a6 --- /dev/null +++ b/server/backend/migration/20200000000000.go @@ -0,0 +1,48 @@ +package migration + +import ( + _ "embed" + "regexp" + "strings" + + log "github.com/sirupsen/logrus" + "gorm.io/gorm/logger" + + "github.com/go-gormigrate/gormigrate/v2" + "gorm.io/gorm" +) + +//go:embed static_data/source-schema.sql +var sourceSchema string + +// migrate20200000000000 +// adds the source schema +func migrate20200000000000() *gormigrate.Migration { + return &gormigrate.Migration{ + ID: "20200000000000", + Migrate: func(tx *gorm.DB) error { + tx = tx.Session(&gorm.Session{Logger: logger.Default.LogMode(logger.Silent)}) + for _, line := range strings.Split(sourceSchema, ";") { + line = strings.TrimSpace(line) + if line == "" { + continue + } + if err := tx.Exec(line).Error; err != nil { + log.WithError(err).WithField("line", line).Error("failed to execute line") + return err + } + } + return nil + }, + Rollback: func(tx *gorm.DB) error { + re := regexp.MustCompile(`create table if not exists (?P\S+)`) + tables := re.FindAllStringSubmatch(sourceSchema, -1) + for _, table := range tables { + if err := tx.Migrator().DropTable(table[re.SubexpIndex("table_name")]); err != nil { + return err + } + } + return nil + }, + } +} diff --git a/server/backend/migration/20210709193000.go b/server/backend/migration/20210709193000.go index 4968b74e..d18a3cb5 100644 --- a/server/backend/migration/20210709193000.go +++ b/server/backend/migration/20210709193000.go @@ -20,7 +20,7 @@ type File struct { // adds a "url" column to the database containing the url the file was downloaded from. // adds a "finished" column to the database that indicates, that a files download is finished. // adds a "fileDownload" cron job that runs every 5 minutes. -func (m TumDBMigrator) migrate20210709193000() *gormigrate.Migration { +func migrate20210709193000() *gormigrate.Migration { return &gormigrate.Migration{ ID: "20210709193000", Migrate: func(tx *gorm.DB) error { diff --git a/server/backend/migration/20220126230000.go b/server/backend/migration/20220126230000.go index dd6662fa..bb871570 100644 --- a/server/backend/migration/20220126230000.go +++ b/server/backend/migration/20220126230000.go @@ -92,7 +92,7 @@ func (r *RoomfinderRooms2maps) TableName() string { // migrate20220126230000 // adds a fulltext index to the roomfinder_rooms table -func (m TumDBMigrator) migrate20220126230000() *gormigrate.Migration { +func migrate20220126230000() *gormigrate.Migration { return &gormigrate.Migration{ ID: "20220126230000", Migrate: func(tx *gorm.DB) error { diff --git a/server/backend/migration/20220713000000.go b/server/backend/migration/20220713000000.go index 09f9ba87..82a5da06 100644 --- a/server/backend/migration/20220713000000.go +++ b/server/backend/migration/20220713000000.go @@ -8,7 +8,7 @@ import ( //migrate20210709193000 -func (m TumDBMigrator) migrate20220713000000() *gormigrate.Migration { +func migrate20220713000000() *gormigrate.Migration { return &gormigrate.Migration{ ID: "20220713000000", Migrate: func(tx *gorm.DB) error { diff --git a/server/backend/migration/20221119131300.go b/server/backend/migration/20221119131300.go index 8ea73cea..fd96ba3b 100644 --- a/server/backend/migration/20221119131300.go +++ b/server/backend/migration/20221119131300.go @@ -16,7 +16,7 @@ import ( //go:embed static_data/iosInitialSchedulingPriorities.json var iosInitialPrioritiesFile []byte -func (m TumDBMigrator) migrate20221119131300() *gormigrate.Migration { +func migrate20221119131300() *gormigrate.Migration { return &gormigrate.Migration{ ID: "20221119131300", Migrate: func(tx *gorm.DB) error { diff --git a/server/backend/migration/20221210000000.go b/server/backend/migration/20221210000000.go index 9ec49d3c..45ac4c47 100644 --- a/server/backend/migration/20221210000000.go +++ b/server/backend/migration/20221210000000.go @@ -9,7 +9,7 @@ import ( // migrate20221210000000 // adds a "canteenHeadCount" cron job that runs every 5 minutes. -func (m TumDBMigrator) migrate20221210000000() *gormigrate.Migration { +func migrate20221210000000() *gormigrate.Migration { return &gormigrate.Migration{ ID: "20221210000000", Migrate: func(tx *gorm.DB) error { diff --git a/server/backend/migration/20230530000000.go b/server/backend/migration/20230530000000.go index add100b8..9e044a70 100644 --- a/server/backend/migration/20230530000000.go +++ b/server/backend/migration/20230530000000.go @@ -26,7 +26,7 @@ type NewExamResultsSubscriber struct { LastNotifiedAt null.Time } -func (m TumDBMigrator) migrate20230530000000() *gormigrate.Migration { +func migrate20230530000000() *gormigrate.Migration { return &gormigrate.Migration{ ID: "20230530000000", Migrate: func(tx *gorm.DB) error { diff --git a/server/backend/migration/20230825000000.go b/server/backend/migration/20230825000000.go index db35ca9d..b35630c0 100644 --- a/server/backend/migration/20230825000000.go +++ b/server/backend/migration/20230825000000.go @@ -9,7 +9,7 @@ import ( // migrate20230825000000 // Removes the ability to run chat cronjobs -func (m TumDBMigrator) migrate20230825000000() *gormigrate.Migration { +func migrate20230825000000() *gormigrate.Migration { return &gormigrate.Migration{ ID: "20230825000000", Migrate: func(tx *gorm.DB) error { diff --git a/server/backend/migration/20230826000000.go b/server/backend/migration/20230826000000.go index 3b8fe0dc..92bb8e40 100644 --- a/server/backend/migration/20230826000000.go +++ b/server/backend/migration/20230826000000.go @@ -20,7 +20,7 @@ func (n *Feedback) TableName() string { // migrate20230826000000 // adds a "feedbackEmail" cron job that runs every 30 minutes. -func (m TumDBMigrator) migrate20230826000000() *gormigrate.Migration { +func migrate20230826000000() *gormigrate.Migration { return &gormigrate.Migration{ ID: "20230826000000", Migrate: func(tx *gorm.DB) error { diff --git a/server/backend/migration/20230904000000.go b/server/backend/migration/20230904000000.go index 6c96cba6..aa15f2e6 100644 --- a/server/backend/migration/20230904000000.go +++ b/server/backend/migration/20230904000000.go @@ -9,7 +9,7 @@ import ( // migrate20230904000000 // Removes ticketsales from the db-enums -func (m TumDBMigrator) migrate20230904000000() *gormigrate.Migration { +func migrate20230904000000() *gormigrate.Migration { return &gormigrate.Migration{ ID: "20230904000000", Migrate: func(tx *gorm.DB) error { diff --git a/server/backend/migration/20230904100000.go b/server/backend/migration/20230904100000.go index fb412917..cd785772 100644 --- a/server/backend/migration/20230904100000.go +++ b/server/backend/migration/20230904100000.go @@ -24,7 +24,7 @@ func (n *NewsSource) TableName() string { // migrate20230904100000 // migrates the crontab from kino to movie crontab -func (m TumDBMigrator) migrate20230904100000() *gormigrate.Migration { +func migrate20230904100000() *gormigrate.Migration { return &gormigrate.Migration{ ID: "20230904100000", Migrate: func(tx *gorm.DB) error { diff --git a/server/backend/migration/20231003000000.go b/server/backend/migration/20231003000000.go index b15eea95..1c0b696f 100644 --- a/server/backend/migration/20231003000000.go +++ b/server/backend/migration/20231003000000.go @@ -84,7 +84,7 @@ var staticData embed.FS // migrate20231003000000 // migrates the static data for the canteen rating system and adds the necessary cronjob entries -func (m TumDBMigrator) migrate20231003000000() *gormigrate.Migration { +func migrate20231003000000() *gormigrate.Migration { return &gormigrate.Migration{ ID: "20231003000000", Migrate: func(tx *gorm.DB) error { diff --git a/server/backend/migration/migration.go b/server/backend/migration/migration.go index f9682f71..c13e32d5 100644 --- a/server/backend/migration/migration.go +++ b/server/backend/migration/migration.go @@ -2,38 +2,27 @@ package migration import ( + "time" + "github.com/TUM-Dev/Campus-Backend/server/model" "github.com/go-gormigrate/gormigrate/v2" log "github.com/sirupsen/logrus" "gorm.io/gorm" ) -// TumDBMigrator contains a reference to our database -type TumDBMigrator struct { - database *gorm.DB - shouldAutoMigrate bool -} - -// New creates a new TumDBMigrator with a database -func New(db *gorm.DB, shouldAutoMigrate bool) TumDBMigrator { - return TumDBMigrator{database: db, shouldAutoMigrate: shouldAutoMigrate} +func autoMigrate(db *gorm.DB) error { + err := db.AutoMigrate( + &model.Crontab{}, + &model.File{}, + &model.NewsSource{}, + &model.NewsAlert{}, + &model.News{}, + &model.CanteenHeadCount{}, + ) + return err } -// Migrate starts the migration either by using AutoMigrate in development environments or manually in prod -func (m TumDBMigrator) Migrate() error { - if m.shouldAutoMigrate { - log.Info("Using automigration") - err := m.database.AutoMigrate( - &model.Crontab{}, - &model.File{}, - &model.NewsSource{}, - &model.NewsAlert{}, - &model.News{}, - &model.CanteenHeadCount{}, - ) - return err - } - log.Info("Using manual migration") +func manualMigrate(db *gorm.DB) error { gormigrateOptions := &gormigrate.Options{ TableName: gormigrate.DefaultOptions.TableName, IDColumnName: gormigrate.DefaultOptions.IDColumnName, @@ -41,20 +30,33 @@ func (m TumDBMigrator) Migrate() error { UseTransaction: true, ValidateUnknownMigrations: true, } - mig := gormigrate.New(m.database, gormigrateOptions, []*gormigrate.Migration{ - m.migrate20210709193000(), - m.migrate20220126230000(), - m.migrate20220713000000(), - m.migrate20221119131300(), - m.migrate20221210000000(), - m.migrate20230825000000(), - m.migrate20230904000000(), - m.migrate20230530000000(), - m.migrate20230904100000(), - m.migrate20230826000000(), - m.migrate20231003000000(), - }) - err := mig.Migrate() - return err + migrations := []*gormigrate.Migration{ + migrate20200000000000(), + migrate20210709193000(), + migrate20220126230000(), + migrate20220713000000(), + migrate20221119131300(), + migrate20221210000000(), + migrate20230825000000(), + migrate20230904000000(), + migrate20230530000000(), + migrate20230904100000(), + migrate20230826000000(), + migrate20231003000000(), + } + return gormigrate.New(db, gormigrateOptions, migrations).Migrate() +} +// Migrate starts the migration either by using AutoMigrate in development environments or manually in prod +func Migrate(db *gorm.DB, shouldAutoMigrate bool) error { + log.WithField("shouldAutoMigrate", shouldAutoMigrate).Info("starting migration") + start := time.Now() + var err error + if shouldAutoMigrate { + err = autoMigrate(db) + } else { + err = manualMigrate(db) + } + log.WithField("elapsed", time.Since(start)).Info("migration done") + return err } diff --git a/deployment/charts/backend/files/source-schema.sql b/server/backend/migration/static_data/source-schema.sql similarity index 59% rename from deployment/charts/backend/files/source-schema.sql rename to server/backend/migration/static_data/source-schema.sql index dad3cfc2..f7fea9c7 100644 --- a/deployment/charts/backend/files/source-schema.sql +++ b/server/backend/migration/static_data/source-schema.sql @@ -2,54 +2,44 @@ CREATE USER 'tca-students' IDENTIFIED BY 'strongpassword'; create table if not exists actions ( - action int auto_increment - primary key, + action int auto_increment primary key, name varchar(50) not null, description mediumtext not null, color varchar(6) not null -) - collate = utf8mb4_unicode_ci - auto_increment = 19; +) collate = utf8mb4_unicode_ci + auto_increment = 19; create table if not exists alarm_ban ( - ban int auto_increment - primary key, + ban int auto_increment primary key, created timestamp /* mariadb-5.3 */ default current_timestamp() not null, ip binary(16) not null, - constraint ip - unique (ip) -) - collate = utf8mb4_unicode_ci; + constraint ip unique (ip) +) collate = utf8mb4_unicode_ci; create table if not exists alarm_log ( - alarm int auto_increment - primary key, + alarm int auto_increment primary key, created timestamp /* mariadb-5.3 */ default current_timestamp() not null, message text not null, send int not null, received int not null, test enum ('true', 'false') default 'false' not null, ip binary(16) not null -) - collate = utf8mb4_unicode_ci; +) collate = utf8mb4_unicode_ci; create table if not exists barrierFree_moreInfo ( - id int(11) unsigned auto_increment - primary key, + id int(11) unsigned auto_increment primary key, title varchar(32) null, category varchar(11) null, url varchar(128) null -) - charset = utf8 - auto_increment = 11; +) charset = utf8 + auto_increment = 11; create table if not exists barrierFree_persons ( - id int(11) unsigned auto_increment - primary key, + id int(11) unsigned auto_increment primary key, name varchar(40) null, telephone varchar(32) null, email varchar(32) null, @@ -57,107 +47,81 @@ create table if not exists barrierFree_persons office varchar(16) null, officeHour varchar(16) null, tumID varchar(24) null -) - charset = utf8 - auto_increment = 19; +) charset = utf8 + auto_increment = 19; create table if not exists card_type ( - card_type int auto_increment - primary key, + card_type int auto_increment primary key, title varchar(255) null -) - auto_increment = 2; +) auto_increment = 2; create table if not exists chat_room ( - room int auto_increment - primary key, + room int auto_increment primary key, name varchar(100) not null, semester varchar(3) null, - constraint `Index 2` - unique (semester, name) -) - collate = utf8mb4_unicode_ci - auto_increment = 1724450; + constraint `Index 2` unique (semester, name) +) collate = utf8mb4_unicode_ci + auto_increment = 1724450; create table if not exists crontab ( cron int auto_increment, - `interval` int default 7200 not null, - lastRun int default 0 not null, + `interval` int default 7200 not null, + lastRun int default 0 not null, type enum ('news', 'mensa', 'chat', 'kino', 'roomfinder', 'ticketsale', 'alarm', 'fileDownload', 'canteenHeadCount') null, - id int null, - constraint cron - unique (cron) -) - collate = utf8mb4_unicode_ci - auto_increment = 44; + id int null, + constraint cron unique (cron) +) collate = utf8mb4_unicode_ci + auto_increment = 44; create table if not exists curricula ( - curriculum int auto_increment - primary key, + curriculum int auto_increment primary key, category enum ('bachelor', 'master') default 'bachelor' not null, name mediumtext not null, url mediumtext not null -) - collate = utf8mb4_unicode_ci - auto_increment = 16; +) collate = utf8mb4_unicode_ci + auto_increment = 16; create table if not exists dish ( - dish int auto_increment - primary key, + dish int auto_increment primary key, name varchar(150) not null, type varchar(20) not null -) - collate = utf8mb4_unicode_ci; +) collate = utf8mb4_unicode_ci; create table if not exists dishflags ( - flag int auto_increment - primary key, + flag int auto_increment primary key, short varchar(10) not null, description varchar(50) not null -) - collate = utf8mb4_unicode_ci; +) collate = utf8mb4_unicode_ci; create table if not exists dish2dishflags ( - dish2dishflags int auto_increment - primary key, + dish2dishflags int auto_increment primary key, dish int not null, flag int not null, - constraint dish - unique (dish, flag), - constraint dish2dishflags_ibfk_1 - foreign key (dish) references dish (dish) - on update cascade on delete cascade, - constraint dish2dishflags_ibfk_2 - foreign key (flag) references dishflags (flag) - on update cascade on delete cascade -) - collate = utf8mb4_unicode_ci; - -create or replace index flag - on dish2dishflags (flag); + constraint dish unique (dish, flag), + constraint dish2dishflags_ibfk_1 foreign key (dish) references dish (dish) on update cascade on delete cascade, + constraint dish2dishflags_ibfk_2 foreign key (flag) references dishflags (flag) on update cascade on delete cascade +) collate = utf8mb4_unicode_ci; + +create or replace index flag on dish2dishflags (flag); create table if not exists faculty ( - faculty int auto_increment - primary key, + faculty int auto_increment primary key, name varchar(150) not null, - constraint name - unique (name) -) - charset = utf8mb4 - auto_increment = 18; + constraint name unique (name) +) charset = utf8mb4 + auto_increment = 18; create table if not exists feedback ( - id int auto_increment - primary key, + id int auto_increment primary key, email_id text charset utf8 null, receiver text charset utf8 null, reply_to text charset utf8 null, @@ -166,26 +130,22 @@ create table if not exists feedback latitude decimal(11, 8) null, longitude decimal(11, 8) null, timestamp datetime /* mariadb-5.3 */ default current_timestamp() null -) - auto_increment = 293; +) auto_increment = 293; create table if not exists files ( - file int auto_increment - primary key, + file int auto_increment primary key, name mediumtext not null, path mediumtext not null, downloads int default 0 not null, url varchar(191) null, downloaded tinyint(1) default 1 null -) - collate = utf8mb4_unicode_ci - auto_increment = 34761; +) collate = utf8mb4_unicode_ci + auto_increment = 34761; create table if not exists kino ( - kino int auto_increment - primary key, + kino int auto_increment primary key, date datetime /* mariadb-5.3 */ not null, created timestamp /* mariadb-5.3 */ default current_timestamp() not null, title text not null, @@ -199,41 +159,32 @@ create table if not exists kino cover int null, trailer text null, link varchar(190) not null, - constraint link - unique (link), - constraint kino_ibfk_1 - foreign key (cover) references files (file) - on update cascade on delete set null -) - collate = utf8mb4_unicode_ci - auto_increment = 219; - -create or replace index cover - on kino (cover); + constraint link unique (link), + constraint kino_ibfk_1 foreign key (cover) references files (file) on update cascade on delete set null +) collate = utf8mb4_unicode_ci + auto_increment = 219; + +create or replace index cover on kino (cover); create table if not exists lecture ( - lecture int auto_increment - primary key, + lecture int auto_increment primary key, title varchar(255) null ); create table if not exists location ( - location int auto_increment - primary key, + location int auto_increment primary key, name text not null, lon float(10, 6) not null, lat float(10, 6) not null, radius int default 1000 not null comment 'in meters' -) - charset = utf8 - auto_increment = 2; +) charset = utf8 + auto_increment = 2; create table if not exists member ( - member int auto_increment - primary key, + member int auto_increment primary key, lrz_id varchar(7) not null, name varchar(150) not null, active_day int default 0 null, @@ -241,16 +192,13 @@ create table if not exists member student_id text null, employee_id text null, external_id text null, - constraint lrz_id - unique (lrz_id) -) - collate = utf8mb4_unicode_ci - auto_increment = 104353; + constraint lrz_id unique (lrz_id) +) collate = utf8mb4_unicode_ci + auto_increment = 104353; create table if not exists card ( - card int auto_increment - primary key, + card int auto_increment primary key, member int null, lecture int null, card_type int null, @@ -264,140 +212,94 @@ create table if not exists card updated_at date not null, duplicate_card int null, aggr_rating float default 0 null, - constraint card_ibfk_1 - foreign key (member) references member (member) - on delete set null, - constraint card_ibfk_2 - foreign key (lecture) references lecture (lecture) - on delete set null, - constraint card_ibfk_3 - foreign key (card_type) references card_type (card_type) - on delete set null, - constraint card_ibfk_4 - foreign key (duplicate_card) references card (card) - on delete set null + constraint card_ibfk_1 foreign key (member) references member (member) on delete set null, + constraint card_ibfk_2 foreign key (lecture) references lecture (lecture) on delete set null, + constraint card_ibfk_3 foreign key (card_type) references card_type (card_type) on delete set null, + constraint card_ibfk_4 foreign key (duplicate_card) references card (card) on delete set null ); -create or replace index card_type - on card (card_type); +create or replace index card_type on card (card_type); -create or replace index duplicate_card - on card (duplicate_card); +create or replace index duplicate_card on card (duplicate_card); -create or replace index lecture - on card (lecture); +create or replace index lecture on card (lecture); -create or replace index member - on card (member); +create or replace index member on card (member); create table if not exists card_box ( - card_box int auto_increment - primary key, + card_box int auto_increment primary key, member int null, title varchar(255) null, duration int not null, - constraint card_box_ibfk_1 - foreign key (member) references member (member) - on delete cascade -) - auto_increment = 6; + constraint card_box_ibfk_1 foreign key (member) references member (member) on delete cascade +) auto_increment = 6; -create or replace index member - on card_box (member); +create or replace index member on card_box (member); create table if not exists card_comment ( - card_comment int auto_increment - primary key, + card_comment int auto_increment primary key, member int null, card int not null, rating int default 0 null, created_at date not null, - constraint card_comment_ibfk_1 - foreign key (member) references member (member) - on delete set null, - constraint card_comment_ibfk_2 - foreign key (card) references card (card) - on delete cascade + constraint card_comment_ibfk_1 foreign key (member) references member (member) on delete set null, + constraint card_comment_ibfk_2 foreign key (card) references card (card) on delete cascade ); -create or replace index card - on card_comment (card); +create or replace index card on card_comment (card); -create or replace index member - on card_comment (member); +create or replace index member on card_comment (member); create table if not exists card_option ( - card_option int auto_increment - primary key, + card_option int auto_increment primary key, card int not null, text varchar(2000) default '' null, is_correct_answer tinyint(1) default 0 null, sort_order int default 0 not null, image varchar(2000) null, - constraint card_option_ibfk_1 - foreign key (card) references card (card) - on delete cascade + constraint card_option_ibfk_1 foreign key (card) references card (card) on delete cascade ); -create or replace index card - on card_option (card); +create or replace index card on card_option (card); create table if not exists chat_message ( - message int auto_increment - primary key, + message int auto_increment primary key, member int not null, room int not null, text longtext not null, created datetime /* mariadb-5.3 */ not null, signature longtext not null, - constraint FK_chat_message_chat_room - foreign key (room) references chat_room (room) - on update cascade on delete cascade, - constraint chat_message_ibfk_1 - foreign key (member) references member (member) - on update cascade on delete cascade -) - collate = utf8mb4_unicode_ci - auto_increment = 1977; - -create or replace index chat_message_b3c09425 - on chat_message (member); - -create or replace index chat_message_ca20ebca - on chat_message (room); + constraint FK_chat_message_chat_room foreign key (room) references chat_room (room) on update cascade on delete cascade, + constraint chat_message_ibfk_1 foreign key (member) references member (member) on update cascade on delete cascade +) collate = utf8mb4_unicode_ci + auto_increment = 1977; + +create or replace index chat_message_b3c09425 on chat_message (member); + +create or replace index chat_message_ca20ebca on chat_message (room); create table if not exists chat_room2members ( - room2members int auto_increment - primary key, + room2members int auto_increment primary key, room int not null, member int not null, - constraint chatroom_id - unique (room, member), - constraint FK_chat_room2members_chat_room - foreign key (room) references chat_room (room) - on update cascade on delete cascade, - constraint chat_room2members_ibfk_2 - foreign key (member) references member (member) - on update cascade on delete cascade -) - collate = utf8mb4_unicode_ci - auto_increment = 63377426; - -create or replace index chat_chatroom_members_29801a33 - on chat_room2members (room); - -create or replace index chat_chatroom_members_b3c09425 - on chat_room2members (member); + constraint chatroom_id unique (room, member), + constraint FK_chat_room2members_chat_room foreign key (room) references chat_room (room) on update cascade on delete cascade, + constraint chat_room2members_ibfk_2 foreign key (member) references member (member) on update cascade on delete cascade +) collate = utf8mb4_unicode_ci + auto_increment = 63377426; + +create or replace index chat_chatroom_members_29801a33 on chat_room2members (room); + +create or replace index chat_chatroom_members_b3c09425 on chat_room2members (member); create table if not exists devices ( - device int auto_increment - primary key, + device int auto_increment primary key, member int null, uuid varchar(50) not null, created timestamp /* mariadb-5.3 */ null, @@ -414,19 +316,14 @@ create table if not exists devices confirmationKey varchar(35) null, keyCreated datetime null, keyConfirmed datetime null, - constraint uuid - unique (uuid), - constraint devices_ibfk_1 - foreign key (member) references member (member) - on update cascade on delete cascade -) - collate = utf8mb4_unicode_ci - auto_increment = 144352; + constraint uuid unique (uuid), + constraint devices_ibfk_1 foreign key (member) references member (member) on update cascade on delete cascade +) collate = utf8mb4_unicode_ci + auto_increment = 144352; create table if not exists device2stats ( - device int default 0 not null - primary key, + device int default 0 not null primary key, LecturesPersonalActivity int default 0 not null, CafeteriaActivity int default 0 not null, WizNavStartActivity int default 0 not null, @@ -468,14 +365,10 @@ create table if not exists device2stats NewsCard2 int default 0 not null, NewsCard3 int default 0 not null, NewsCard7 int default 0 not null, - constraint device2stats_ibfk_2 - foreign key (device) references devices (device) - on update cascade on delete cascade -) - collate = utf8mb4_unicode_ci; + constraint device2stats_ibfk_2 foreign key (device) references devices (device) on update cascade on delete cascade +) collate = utf8mb4_unicode_ci; -create or replace index member - on devices (member); +create or replace index member on devices (member); create table if not exists members_card ( @@ -484,144 +377,105 @@ create table if not exists members_card card_box int null, last_answered_active_day int null, primary key (member, card), - constraint members_card_ibfk_1 - foreign key (member) references member (member) - on delete cascade, - constraint members_card_ibfk_2 - foreign key (card) references card (card) - on delete cascade, - constraint members_card_ibfk_3 - foreign key (card_box) references card_box (card_box) - on delete set null + constraint members_card_ibfk_1 foreign key (member) references member (member) on delete cascade, + constraint members_card_ibfk_2 foreign key (card) references card (card) on delete cascade, + constraint members_card_ibfk_3 foreign key (card_box) references card_box (card_box) on delete set null ); -create or replace index card - on members_card (card); +create or replace index card on members_card (card); -create or replace index card_box - on members_card (card_box); +create or replace index card_box on members_card (card_box); create table if not exists members_card_answer_history ( - members_card_answer_history int auto_increment - primary key, + members_card_answer_history int auto_increment primary key, member int not null, card int null, card_box int null, answer varchar(2000) null, answer_score float(10, 2) default 0.00 null, created_at date not null, - constraint members_card_answer_history_ibfk_1 - foreign key (member) references member (member) - on delete cascade, - constraint members_card_answer_history_ibfk_2 - foreign key (card) references card (card) - on delete set null, - constraint members_card_answer_history_ibfk_3 - foreign key (card_box) references card_box (card_box) - on delete set null + constraint members_card_answer_history_ibfk_1 foreign key (member) references member (member) on delete cascade, + constraint members_card_answer_history_ibfk_2 foreign key (card) references card (card) on delete set null, + constraint members_card_answer_history_ibfk_3 foreign key (card_box) references card_box (card_box) on delete set null ); -create or replace index card - on members_card_answer_history (card); +create or replace index card on members_card_answer_history (card); -create or replace index card_box - on members_card_answer_history (card_box); +create or replace index card_box on members_card_answer_history (card_box); -create or replace index member - on members_card_answer_history (member); +create or replace index member on members_card_answer_history (member); create table if not exists mensa ( - mensa int auto_increment - primary key, + mensa int auto_increment primary key, id int null, name mediumtext not null, address mediumtext not null, latitude float(10, 6) default 0.000000 not null, longitude float(10, 6) default 0.000000 not null, - constraint id - unique (id) -) - collate = utf8mb4_unicode_ci - auto_increment = 17; + constraint id unique (id) +) collate = utf8mb4_unicode_ci + auto_increment = 17; create table if not exists dish2mensa ( - dish2mensa int auto_increment - primary key, + dish2mensa int auto_increment primary key, mensa int not null, dish int not null, date date not null, created datetime /* mariadb-5.3 */ not null, modifierd timestamp /* mariadb-5.3 */ default '0000-00-00 00:00:00' not null on update current_timestamp(), - constraint dish2mensa_ibfk_1 - foreign key (mensa) references mensa (mensa) - on update cascade on delete cascade, - constraint dish2mensa_ibfk_2 - foreign key (dish) references dish (dish) - on update cascade on delete cascade -) - collate = utf8mb4_unicode_ci; + constraint dish2mensa_ibfk_1 foreign key (mensa) references mensa (mensa) on update cascade on delete cascade, + constraint dish2mensa_ibfk_2 foreign key (dish) references dish (dish) on update cascade on delete cascade +) collate = utf8mb4_unicode_ci; -create or replace index dish - on dish2mensa (dish); +create or replace index dish on dish2mensa (dish); -create or replace index mensa - on dish2mensa (mensa); +create or replace index mensa on dish2mensa (mensa); create table if not exists mensaplan_mensa ( - id int auto_increment - primary key, + id int auto_increment primary key, name varchar(100) not null, latitude double null, longitude double null, webid int null, category varchar(50) not null -) - engine = MyISAM - collate = utf8mb4_unicode_ci - auto_increment = 30; +) engine = MyISAM + collate = utf8mb4_unicode_ci + auto_increment = 30; create table if not exists mensaprices ( - price int auto_increment - primary key, + price int auto_increment primary key, created timestamp /* mariadb-5.3 */ default current_timestamp() not null, person mediumtext not null, type mediumtext not null, typeLong mediumtext not null, typeNumber int not null, value decimal not null -) - collate = utf8mb4_unicode_ci; +) collate = utf8mb4_unicode_ci; create table if not exists migrations ( - id varchar(255) not null - primary key + id varchar(255) not null primary key ); create table if not exists newsSource ( - source int auto_increment - primary key, + source int auto_increment primary key, title mediumtext not null, url mediumtext null, - icon int null, + icon int not null, hook enum ('newspread', 'impulsivHook') null, - constraint newsSource_ibfk_1 - foreign key (icon) references files (file) - on update cascade on delete set null -) - collate = utf8mb4_unicode_ci - auto_increment = 17; + constraint newsSource_ibfk_1 foreign key (icon) references files (file) on update cascade on delete cascade +) collate = utf8mb4_unicode_ci + auto_increment = 17; create table if not exists news ( - news int auto_increment - primary key, + news int auto_increment primary key, date datetime /* mariadb-5.3 */ not null, created timestamp /* mariadb-5.3 */ default current_timestamp() not null, title tinytext not null, @@ -630,57 +484,42 @@ create table if not exists news link varchar(190) not null, image text null, file int null, - constraint link - unique (link), - constraint news_ibfk_1 - foreign key (src) references newsSource (source) - on update cascade on delete cascade, - constraint news_ibfk_2 - foreign key (file) references files (file) - on update cascade on delete set null -) - collate = utf8mb4_unicode_ci - auto_increment = 770113; - -create or replace index file - on news (file); - -create or replace index src - on news (src); - -create or replace index icon - on newsSource (icon); + constraint link unique (link), + constraint news_ibfk_1 foreign key (src) references newsSource (source) on update cascade on delete cascade, + constraint news_ibfk_2 foreign key (file) references files (file) on update cascade on delete set null +) collate = utf8mb4_unicode_ci + auto_increment = 770113; + +create or replace index file on news (file); + +create or replace index src on news (src); + +create or replace index icon on newsSource (icon); create table if not exists news_alert ( - news_alert int auto_increment - primary key, + news_alert int auto_increment primary key, file int null, name varchar(100) null, link text null, created timestamp /* mariadb-5.3 */ default current_timestamp() not null, `from` datetime /* mariadb-5.3 */ default current_timestamp() not null, `to` datetime /* mariadb-5.3 */ default current_timestamp() not null, - constraint FK_File - unique (file) -) - charset = utf8mb4 - auto_increment = 7; + constraint FK_File unique (file) +) charset = utf8mb4 + auto_increment = 7; create table if not exists notification_type ( - type int auto_increment - primary key, + type int auto_increment primary key, name text not null, confirmation enum ('true', 'false') default 'false' not null -) - charset = utf8 - auto_increment = 4; +) charset = utf8 + auto_increment = 4; create table if not exists notification ( - notification int auto_increment - primary key, + notification int auto_increment primary key, type int not null, location int null, title text not null, @@ -688,21 +527,14 @@ create table if not exists notification created timestamp /* mariadb-5.3 */ default current_timestamp() not null, signature text null, silent tinyint(1) default 0 not null, - constraint notification_ibfk_1 - foreign key (type) references notification_type (type) - on update cascade on delete cascade, - constraint notification_ibfk_2 - foreign key (location) references location (location) - on update cascade on delete set null -) - charset = utf8 - auto_increment = 107; - -create or replace index location - on notification (location); - -create or replace index type - on notification (type); + constraint notification_ibfk_1 foreign key (type) references notification_type (type) on update cascade on delete cascade, + constraint notification_ibfk_2 foreign key (location) references location (location) on update cascade on delete set null +) charset = utf8 + auto_increment = 107; + +create or replace index location on notification (location); + +create or replace index type on notification (type); create table if not exists notification_confirmation ( @@ -712,20 +544,15 @@ create table if not exists notification_confirmation created timestamp /* mariadb-5.3 */ default current_timestamp() not null, received timestamp /* mariadb-5.3 */ null, primary key (notification, device), - constraint notification_confirmation_ibfk_1 - foreign key (notification) references notification (notification), - constraint notification_confirmation_ibfk_2 - foreign key (device) references devices (device) -) - charset = utf8; + constraint notification_confirmation_ibfk_1 foreign key (notification) references notification (notification), + constraint notification_confirmation_ibfk_2 foreign key (device) references devices (device) +) charset = utf8; -create or replace index device - on notification_confirmation (device); +create or replace index device on notification_confirmation (device); create table if not exists openinghours ( - id int auto_increment - primary key, + id int auto_increment primary key, category varchar(20) not null, name varchar(60) not null, address varchar(140) not null, @@ -736,31 +563,26 @@ create table if not exists openinghours url varchar(300) not null, language varchar(2) default 'de' null, reference_id int default -1 null -) - collate = utf8mb4_unicode_ci - auto_increment = 113; +) collate = utf8mb4_unicode_ci + auto_increment = 113; create table if not exists question ( - question int auto_increment - primary key, + question int auto_increment primary key, member int not null, text text not null, created timestamp /* mariadb-5.3 */ default current_timestamp() not null, end timestamp /* mariadb-5.3 */ null -) - auto_increment = 282; +) auto_increment = 282; -create or replace index member - on question (member); +create or replace index member on question (member); create table if not exists question2answer ( question int not null, answer int not null, member int not null, - constraint question - unique (question, member) + constraint question unique (question, member) ); create table if not exists question2faculty @@ -768,29 +590,21 @@ create table if not exists question2faculty question int not null, faculty int not null, primary key (question, faculty), - constraint question2faculty_ibfk_1 - foreign key (question) references question (question) - on update cascade on delete cascade, - constraint question2faculty_ibfk_2 - foreign key (faculty) references faculty (faculty) - on update cascade on delete cascade + constraint question2faculty_ibfk_1 foreign key (question) references question (question) on update cascade on delete cascade, + constraint question2faculty_ibfk_2 foreign key (faculty) references faculty (faculty) on update cascade on delete cascade ); -create or replace index faculty - on question2faculty (faculty); +create or replace index faculty on question2faculty (faculty); create table if not exists questionAnswers ( - answer int auto_increment - primary key, + answer int auto_increment primary key, text text not null -) - auto_increment = 3; +) auto_increment = 3; create table if not exists reports ( - report int auto_increment - primary key, + report int auto_increment primary key, device int null, created timestamp /* mariadb-5.3 */ default current_timestamp() not null, fixed enum ('true', 'false') default 'false' not null, @@ -810,32 +624,24 @@ create table if not exists reports screenHeight varchar(100) not null, screenOrientation varchar(100) not null, screenDpi varchar(100) not null, - constraint reports_ibfk_3 - foreign key (device) references devices (device) - on update cascade on delete set null -) - collate = utf8mb4_unicode_ci; + constraint reports_ibfk_3 foreign key (device) references devices (device) on update cascade on delete set null +) collate = utf8mb4_unicode_ci; -create or replace index device - on reports (device); +create or replace index device on reports (device); create table if not exists rights ( - `right` int auto_increment - primary key, + `right` int auto_increment primary key, name varchar(100) null, description mediumtext not null, category int default 0 not null, - constraint Unquie - unique (name) -) - collate = utf8mb4_unicode_ci - auto_increment = 14; + constraint Unquie unique (name) +) collate = utf8mb4_unicode_ci + auto_increment = 14; create table if not exists menu ( - menu int auto_increment - primary key, + menu int auto_increment primary key, `right` int null, parent int null, name varchar(255) null, @@ -844,126 +650,96 @@ create table if not exists menu icon varchar(200) not null, class varchar(200) not null, position int default 0 not null, - constraint menu_ibfk_1 - foreign key (`right`) references rights (`right`) - on update cascade on delete set null, - constraint menu_ibfk_2 - foreign key (parent) references menu (menu) - on update cascade on delete set null -) - collate = utf8mb4_unicode_ci - auto_increment = 25; - -create or replace index parent - on menu (parent); - -create or replace index `right` - on menu (`right`); + constraint menu_ibfk_1 foreign key (`right`) references rights (`right`) on update cascade on delete set null, + constraint menu_ibfk_2 foreign key (parent) references menu (menu) on update cascade on delete set null +) collate = utf8mb4_unicode_ci + auto_increment = 25; + +create or replace index parent on menu (parent); + +create or replace index `right` on menu (`right`); create table if not exists modules ( - module int auto_increment - primary key, + module int auto_increment primary key, name varchar(255) null, `right` int null, - constraint fkMod2Rights - foreign key (`right`) references rights (`right`) - on update cascade on delete set null -) - collate = utf8mb4_unicode_ci - auto_increment = 31; + constraint fkMod2Rights foreign key (`right`) references rights (`right`) on update cascade on delete set null +) collate = utf8mb4_unicode_ci + auto_increment = 31; -create or replace index module_right - on modules (`right`); +create or replace index module_right on modules (`right`); create table if not exists roles ( - role int auto_increment - primary key, + role int auto_increment primary key, name varchar(50) not null, description mediumtext not null -) - collate = utf8mb4_unicode_ci - auto_increment = 6; +) collate = utf8mb4_unicode_ci + auto_increment = 6; create table if not exists roles2rights ( role int not null, `right` int not null, primary key (role, `right`), - constraint fkRight - foreign key (`right`) references rights (`right`) - on delete cascade, - constraint fkRole - foreign key (role) references roles (role) - on delete cascade -) - collate = utf8mb4_unicode_ci; - -create or replace index fkRight_idx - on roles2rights (`right`); + constraint fkRight foreign key (`right`) references rights (`right`) on delete cascade, + constraint fkRole foreign key (role) references roles (role) on delete cascade +) collate = utf8mb4_unicode_ci; + +create or replace index fkRight_idx on roles2rights (`right`); create table if not exists roomfinder_building2area ( area_id int not null, - building_nr varchar(8) not null - primary key, + building_nr varchar(8) not null primary key, campus char not null, name varchar(32) not null -) - charset = utf8mb4; +) charset = utf8mb4; grant select on table roomfinder_building2area to 'tca-students'; create table if not exists roomfinder_buildings ( - building_nr varchar(8) not null - primary key, + building_nr varchar(8) not null primary key, utm_zone varchar(4) null, utm_easting varchar(32) null, utm_northing varchar(32) null, default_map_id int null -) - charset = utf8mb4; +) charset = utf8mb4; grant select on table roomfinder_buildings to 'tca-students'; create table if not exists roomfinder_buildings2gps ( - id varchar(8) default '' not null - primary key, + id varchar(8) default '' not null primary key, latitude varchar(30) null, longitude varchar(30) null -) - charset = utf8mb4; +) charset = utf8mb4; create table if not exists roomfinder_buildings2maps ( building_nr varchar(8) not null, map_id int not null, primary key (building_nr, map_id) -) - charset = utf8mb4; +) charset = utf8mb4; grant select on table roomfinder_buildings2maps to 'tca-students'; create table if not exists roomfinder_maps ( - map_id int not null - primary key, + map_id int not null primary key, description varchar(64) not null, scale int not null, width int not null, height int not null -) - charset = utf8mb4; +) charset = utf8mb4; grant select on table roomfinder_maps to 'tca-students'; create table if not exists roomfinder_rooms ( - room_id int not null - primary key, + room_id int not null primary key, room_code varchar(32) null, building_nr varchar(8) null, arch_id varchar(16) null, @@ -977,8 +753,7 @@ create table if not exists roomfinder_rooms utm_northing varchar(32) null, unit_id int null, default_map_id int null -) - charset = utf8mb4; +) charset = utf8mb4; grant select on table roomfinder_rooms to 'tca-students'; @@ -987,8 +762,7 @@ create table if not exists roomfinder_rooms2maps room_id int not null, map_id int not null, primary key (room_id, map_id) -) - charset = utf8mb4; +) charset = utf8mb4; create table if not exists roomfinder_schedules ( @@ -998,28 +772,22 @@ create table if not exists roomfinder_schedules title varchar(64) not null, event_id int not null, course_code varchar(32) null, - constraint `unique` - unique (room_id, start, end) -) - charset = utf8mb4; + constraint `unique` unique (room_id, start, end) +) charset = utf8mb4; grant select on table roomfinder_schedules to 'tca-students'; create table if not exists sessions ( - session varchar(255) charset utf8 not null - primary key, + session varchar(255) charset utf8 not null primary key, access int unsigned null, data text null, - constraint session - unique (session) -) - collate = utf8mb4_unicode_ci; + constraint session unique (session) +) collate = utf8mb4_unicode_ci; create table if not exists tag ( - tag int auto_increment - primary key, + tag int auto_increment primary key, title varchar(255) null ); @@ -1028,42 +796,32 @@ create table if not exists card2tag tag int not null, card int not null, primary key (tag, card), - constraint card2tag_ibfk_1 - foreign key (tag) references tag (tag) - on delete cascade, - constraint card2tag_ibfk_2 - foreign key (card) references card (card) - on delete cascade + constraint card2tag_ibfk_1 foreign key (tag) references tag (tag) on delete cascade, + constraint card2tag_ibfk_2 foreign key (card) references card (card) on delete cascade ); -create or replace index card - on card2tag (card); +create or replace index card on card2tag (card); create table if not exists ticket_admin ( - ticket_admin int auto_increment - primary key, + ticket_admin int auto_increment primary key, `key` text not null, created timestamp /* mariadb-5.3 */ default current_timestamp() not null, active tinyint(1) default 0 not null, comment text null -) - charset = utf8 - auto_increment = 48; +) charset = utf8 + auto_increment = 48; create table if not exists ticket_group ( - ticket_group int auto_increment - primary key, + ticket_group int auto_increment primary key, description text not null -) - charset = utf8 - auto_increment = 2; +) charset = utf8 + auto_increment = 2; create table if not exists event ( - event int auto_increment - primary key, + event int auto_increment primary key, news int null, kino int null, file int null, @@ -1074,84 +832,57 @@ create table if not exists event start datetime /* mariadb-5.3 */ null, end datetime /* mariadb-5.3 */ null, ticket_group int default 1 null, - constraint fkEventFile - foreign key (file) references files (file) - on update cascade on delete set null, - constraint fkEventGroup - foreign key (ticket_group) references ticket_group (ticket_group), - constraint fkKino - foreign key (kino) references kino (kino) - on update cascade on delete set null, - constraint fkNews - foreign key (news) references news (news) - on update cascade on delete set null -) - charset = utf8 - auto_increment = 39; - -create or replace index file - on event (file); - -create or replace fulltext index searchTitle - on event (title); + constraint fkEventFile foreign key (file) references files (file) on update cascade on delete set null, + constraint fkEventGroup foreign key (ticket_group) references ticket_group (ticket_group), + constraint fkKino foreign key (kino) references kino (kino) on update cascade on delete set null, + constraint fkNews foreign key (news) references news (news) on update cascade on delete set null +) charset = utf8 + auto_increment = 39; + +create or replace index file on event (file); + +create or replace fulltext index searchTitle on event (title); create table if not exists ticket_admin2group ( - ticket_admin2group int auto_increment - primary key, + ticket_admin2group int auto_increment primary key, ticket_admin int not null, ticket_group int not null, - constraint fkTicketAdmin - foreign key (ticket_admin) references ticket_admin (ticket_admin) - on update cascade on delete cascade, - constraint fkTicketGroup - foreign key (ticket_group) references ticket_group (ticket_group) - on update cascade on delete cascade -) - charset = utf8 - auto_increment = 10; - -create or replace index ticket_admin - on ticket_admin2group (ticket_admin); - -create or replace index ticket_group - on ticket_admin2group (ticket_group); + constraint fkTicketAdmin foreign key (ticket_admin) references ticket_admin (ticket_admin) on update cascade on delete cascade, + constraint fkTicketGroup foreign key (ticket_group) references ticket_group (ticket_group) on update cascade on delete cascade +) charset = utf8 + auto_increment = 10; + +create or replace index ticket_admin on ticket_admin2group (ticket_admin); + +create or replace index ticket_group on ticket_admin2group (ticket_group); create table if not exists ticket_payment ( - ticket_payment int auto_increment - primary key, + ticket_payment int auto_increment primary key, name varchar(50) not null, min_amount int null, max_amount int null, config text not null -) - charset = utf8 - auto_increment = 3; +) charset = utf8 + auto_increment = 3; create table if not exists ticket_type ( - ticket_type int auto_increment - primary key, + ticket_type int auto_increment primary key, event int not null, ticket_payment int not null, price double not null, contingent int not null, description varchar(100) not null, - constraint fkEvent - foreign key (event) references event (event) - on update cascade on delete cascade, - constraint fkPayment - foreign key (ticket_payment) references ticket_payment (ticket_payment) - on update cascade -) - charset = utf8 - auto_increment = 57; + constraint fkEvent foreign key (event) references event (event) on update cascade on delete cascade, + constraint fkPayment foreign key (ticket_payment) references ticket_payment (ticket_payment) on update cascade +) charset = utf8 + auto_increment = 57; create table if not exists ticket_history ( - ticket_history int auto_increment - primary key, + ticket_history int auto_increment primary key, member int not null, ticket_payment int null, ticket_type int not null, @@ -1159,46 +890,32 @@ create table if not exists ticket_history redemption datetime /* mariadb-5.3 */ null, created timestamp /* mariadb-5.3 */ default current_timestamp() not null, code char(128) not null, - constraint fkMember - foreign key (member) references member (member) - on update cascade on delete cascade, - constraint fkTicketPayment - foreign key (ticket_payment) references ticket_payment (ticket_payment) - on update cascade, - constraint fkTicketType - foreign key (ticket_type) references ticket_type (ticket_type) - on update cascade -) - charset = utf8 - auto_increment = 776; - -create or replace index member - on ticket_history (member); - -create or replace index ticket_payment - on ticket_history (ticket_payment); - -create or replace index ticket_type - on ticket_history (ticket_type); - -create or replace index event - on ticket_type (event); - -create or replace index ticket_payment - on ticket_type (ticket_payment); + constraint fkMember foreign key (member) references member (member) on update cascade on delete cascade, + constraint fkTicketPayment foreign key (ticket_payment) references ticket_payment (ticket_payment) on update cascade, + constraint fkTicketType foreign key (ticket_type) references ticket_type (ticket_type) on update cascade +) charset = utf8 + auto_increment = 776; + +create or replace index member on ticket_history (member); + +create or replace index ticket_payment on ticket_history (ticket_payment); + +create or replace index ticket_type on ticket_history (ticket_type); + +create or replace index event on ticket_type (event); + +create or replace index ticket_payment on ticket_type (ticket_payment); create table if not exists update_note ( - version_code int not null - primary key, + version_code int not null primary key, version_name text null, message text null ); create table if not exists users ( - user int auto_increment - primary key, + user int auto_increment primary key, username varchar(7) null, firstname varchar(100) null, surname varchar(100) null, @@ -1211,93 +928,64 @@ create table if not exists users tum_id_employee varchar(50) null comment 'OBFUSCATED_ID_B', tum_id_alumni varchar(50) null comment 'OBFUSCATED_ID_EXT', tum_id_preferred varchar(50) null comment 'OBFUSCATED_ID_BEVORZUGT', - constraint username - unique (username) -) - collate = utf8mb4_unicode_ci - auto_increment = 434; + constraint username unique (username) +) collate = utf8mb4_unicode_ci + auto_increment = 434; create table if not exists log ( - log int auto_increment - primary key, + log int auto_increment primary key, time int not null, user_executed int null, user_affected int null, action int null, comment varchar(255) not null, - constraint fkLog2Actions - foreign key (action) references actions (action) - on update set null on delete set null, - constraint fkLog2UsersAf - foreign key (user_affected) references users (user) - on update set null on delete set null, - constraint fkLog2UsersEx - foreign key (user_executed) references users (user) - on update set null on delete set null -) - collate = utf8mb4_unicode_ci; - -create or replace index action - on log (action); - -create or replace index user - on log (user_executed); - -create or replace index user_affected - on log (user_affected); + constraint fkLog2Actions foreign key (action) references actions (action) on update set null on delete set null, + constraint fkLog2UsersAf foreign key (user_affected) references users (user) on update set null on delete set null, + constraint fkLog2UsersEx foreign key (user_executed) references users (user) on update set null on delete set null +) collate = utf8mb4_unicode_ci; + +create or replace index action on log (action); + +create or replace index user on log (user_executed); + +create or replace index user_affected on log (user_affected); create table if not exists recover ( - recover int auto_increment - primary key, + recover int auto_increment primary key, user int not null, created int not null, hash varchar(190) not null, ip varchar(255) not null, - constraint hash - unique (hash), - constraint fkRecover2User - foreign key (user) references users (user) - on delete cascade -) - collate = utf8mb4_unicode_ci; + constraint hash unique (hash), + constraint fkRecover2User foreign key (user) references users (user) on delete cascade +) collate = utf8mb4_unicode_ci; -create or replace index user - on recover (user); +create or replace index user on recover (user); create table if not exists users2info ( - user int not null - primary key, + user int not null primary key, firstname varchar(255) not null, surname varchar(255) not null, lastPwChange int not null, pager int default 15 null, - constraint fkUsers - foreign key (user) references users (user) - on update cascade on delete cascade -) - collate = utf8mb4_unicode_ci; + constraint fkUsers foreign key (user) references users (user) on update cascade on delete cascade +) collate = utf8mb4_unicode_ci; create table if not exists users2roles ( user int not null, role int not null, primary key (user, role), - constraint fkUser2RolesRole - foreign key (role) references roles (role) - on update cascade on delete cascade, - constraint fkUser2RolesUser - foreign key (user) references users (user) - on update cascade on delete cascade -) - collate = utf8mb4_unicode_ci; + constraint fkUser2RolesRole foreign key (role) references roles (role) on update cascade on delete cascade, + constraint fkUser2RolesUser foreign key (user) references users (user) on update cascade on delete cascade +) collate = utf8mb4_unicode_ci; create table if not exists wifi_measurement ( - id int(20) unsigned auto_increment - primary key, + id int(20) unsigned auto_increment primary key, date date not null, SSID varchar(32) not null, BSSID varchar(64) not null, @@ -1305,5 +993,4 @@ create table if not exists wifi_measurement accuracyInMeters float not null, latitude double not null, longitude double not null -) - collate = utf8mb4_unicode_ci; +) collate = utf8mb4_unicode_ci; diff --git a/server/main.go b/server/main.go index 01b65ca0..516727fd 100644 --- a/server/main.go +++ b/server/main.go @@ -7,34 +7,24 @@ import ( "net" "net/http" "net/textproto" - "os" - "strings" "time" + "github.com/TUM-Dev/Campus-Backend/server/utils" "google.golang.org/grpc/reflection" "github.com/prometheus/client_golang/prometheus/promhttp" - "github.com/TUM-Dev/Campus-Backend/server/env" - "github.com/makasim/sentryhook" - pb "github.com/TUM-Dev/Campus-Backend/server/api/tumdev" "github.com/TUM-Dev/Campus-Backend/server/backend" "github.com/TUM-Dev/Campus-Backend/server/backend/cron" - "github.com/TUM-Dev/Campus-Backend/server/backend/migration" "github.com/getsentry/sentry-go" "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" - "github.com/onrik/gorm-logrus" log "github.com/sirupsen/logrus" "github.com/soheilhy/cmux" "golang.org/x/sync/errgroup" "google.golang.org/grpc" - "google.golang.org/grpc/codes" "google.golang.org/grpc/credentials/insecure" "google.golang.org/grpc/metadata" - "google.golang.org/grpc/status" - "gorm.io/driver/mysql" - "gorm.io/gorm" ) const httpPort = ":50051" @@ -46,10 +36,10 @@ var Version = "dev" var swagfs embed.FS func main() { - setupTelemetry() + utils.SetupTelemetry(Version) defer sentry.Flush(10 * time.Second) // make sure that sentry handles shutdowns gracefully - db := setupDB() + db := utils.SetupDB() // Create any other background services (these shouldn't do any long-running work here) cronService := cron.New(db) @@ -135,55 +125,6 @@ func StreamRequestLogger(srv any, stream grpc.ServerStream, info *grpc.StreamSer return err } -// setupDB connects to the database and migrates it if necessary -func setupDB() *gorm.DB { - dbHost := os.Getenv("DB_DSN") - if dbHost == "" { - log.Fatal("Failed to start! The 'DB_DSN' environment variable is not defined. Take a look at the README.md for more details.") - } - - log.Info("Connecting to dsn") - db, err := gorm.Open(mysql.Open(dbHost), &gorm.Config{Logger: gorm_logrus.New()}) - if err != nil { - log.WithError(err).Fatal("failed to connect database") - } - - // Migrate the schema - // currently not activated as - if err := migration.New(db, false).Migrate(); err != nil { - log.WithError(err).Fatal("Failed to migrate database") - } - return db -} - -// setupTelemetry initializes our telemetry stack -// - sentry to be connected with log -// - logrus to -func setupTelemetry() { - environment := "development" - log.SetLevel(log.TraceLevel) - if env.IsProd() { - log.SetLevel(log.InfoLevel) - environment = "production" - log.SetFormatter(&log.JSONFormatter{}) // simpler to query but harder to parse in the console - } - - if sentryDSN := os.Getenv("SENTRY_DSN"); sentryDSN != "" { - if err := sentry.Init(sentry.ClientOptions{ - Dsn: sentryDSN, - AttachStacktrace: true, - Release: Version, - Dist: Version, // see https://github.com/getsentry/sentry-react-native/issues/516 why this is equal - Environment: environment, - }); err != nil { - log.WithError(err).Error("Sentry initialization failed") - } - log.AddHook(sentryhook.New([]log.Level{log.PanicLevel, log.FatalLevel, log.ErrorLevel, log.WarnLevel})) - } else { - log.Info("continuing without sentry") - } -} - // addMethodNameInterceptor adds the method name (e.g. "ListNewsSources") to the metadata as x-campus-method for later use (currently logging the devices api usage) func addMethodNameInterceptor(ctx context.Context, method string, req interface{}, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { ctx = metadata.AppendToOutgoingContext(ctx, "x-campus-method", method) @@ -192,49 +133,11 @@ func addMethodNameInterceptor(ctx context.Context, method string, req interface{ // errorHandler translates gRPC raised by the backend into HTTP errors. func errorHandler(_ context.Context, _ *runtime.ServeMux, _ runtime.Marshaler, w http.ResponseWriter, _ *http.Request, err error) { - errorResp := errorResponse{Error: "Internal Server Error", StatusCode: http.StatusInternalServerError} - - if strings.HasPrefix(err.Error(), "no device id") { - errorResp.Error = "Not Authorized" - errorResp.StatusCode = http.StatusForbidden - } - - if s, ok := status.FromError(err); ok { - switch s.Code() { - case codes.NotFound: - errorResp.Error = "Not Found" - errorResp.StatusCode = http.StatusNotFound - case codes.Unimplemented: - errorResp.Error = "Not Implemented" - errorResp.StatusCode = http.StatusNotImplemented - case codes.InvalidArgument: - errorResp.Error = "Invalid Argument" - errorResp.StatusCode = http.StatusBadRequest - case codes.Internal: - errorResp.Error = "Internal Server Error" - errorResp.StatusCode = http.StatusInternalServerError - } - - if s.Message() != "" { - errorResp.Error = s.Message() - } - - if s.Details() != nil && len(s.Details()) > 0 { - errorResp.Details = s.Details() - } - } - + errorResp := utils.GrpcErrorToWebError(err) w.Header().Set("Content-Type", "application/json") w.WriteHeader(errorResp.StatusCode) if err = json.NewEncoder(w).Encode(errorResp); err != nil { log.WithError(err).Error("Marshal error response failed") - return } } - -type errorResponse struct { - Error string `json:"error"` - Details []interface{} `json:"details,omitempty"` - StatusCode int `json:"-"` -} diff --git a/server/utils/db.go b/server/utils/db.go new file mode 100644 index 00000000..59d7bdb4 --- /dev/null +++ b/server/utils/db.go @@ -0,0 +1,37 @@ +package utils + +import ( + "os" + + "github.com/TUM-Dev/Campus-Backend/server/backend/migration" + gormlogrus "github.com/onrik/gorm-logrus" + log "github.com/sirupsen/logrus" + "gorm.io/driver/mysql" + "gorm.io/gorm" +) + +// SetupDB connects to the database and migrates it if necessary +func SetupDB() *gorm.DB { + dbHost := os.Getenv("DB_DSN") + if dbHost == "" { + log.Fatal("Failed to start! The 'DB_DSN' environment variable is not defined. Take a look at the README.md for more details.") + } + + log.Info("Connecting to dsn") + db, err := gorm.Open(mysql.Open(dbHost), &gorm.Config{Logger: gormlogrus.New()}) + if err != nil { + log.WithError(err).Fatal("failed to connect database") + } + + // Migrate the schema + // currently not activated as + if err := migration.Migrate(db, false); err != nil { + log.WithError(err).Fatal("Failed to migrate database") + } + + if os.Getenv("CI_EXIT_AFTER_MIGRATION") == "true" { + log.Info("Exiting after migration") + os.Exit(0) + } + return db +} diff --git a/server/utils/grpc_to_web.go b/server/utils/grpc_to_web.go new file mode 100644 index 00000000..6571369c --- /dev/null +++ b/server/utils/grpc_to_web.go @@ -0,0 +1,50 @@ +package utils + +import ( + "net/http" + "strings" + + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +func GrpcErrorToWebError(err error) ErrorResponse { + errorResp := ErrorResponse{Error: "Internal Server Error", StatusCode: http.StatusInternalServerError} + + if strings.HasPrefix(err.Error(), "no device id") { + errorResp.Error = "Not Authorized" + errorResp.StatusCode = http.StatusForbidden + } + + if s, ok := status.FromError(err); ok { + switch s.Code() { + case codes.NotFound: + errorResp.Error = "Not Found" + errorResp.StatusCode = http.StatusNotFound + case codes.Unimplemented: + errorResp.Error = "Not Implemented" + errorResp.StatusCode = http.StatusNotImplemented + case codes.InvalidArgument: + errorResp.Error = "Invalid Argument" + errorResp.StatusCode = http.StatusBadRequest + case codes.Internal: + errorResp.Error = "Internal Server Error" + errorResp.StatusCode = http.StatusInternalServerError + } + + if s.Message() != "" { + errorResp.Error = s.Message() + } + + if s.Details() != nil && len(s.Details()) > 0 { + errorResp.Details = s.Details() + } + } + return errorResp +} + +type ErrorResponse struct { + Error string `json:"error"` + Details []interface{} `json:"details,omitempty"` + StatusCode int `json:"-"` +} diff --git a/server/utils/telemetry.go b/server/utils/telemetry.go new file mode 100644 index 00000000..fd0ecf66 --- /dev/null +++ b/server/utils/telemetry.go @@ -0,0 +1,38 @@ +package utils + +import ( + "os" + + "github.com/TUM-Dev/Campus-Backend/server/env" + "github.com/getsentry/sentry-go" + "github.com/makasim/sentryhook" + log "github.com/sirupsen/logrus" +) + +// SetupTelemetry initializes our telemetry stack +// - sentry to be connected with log +// - logrus to +func SetupTelemetry(Version string) { + environment := "development" + log.SetLevel(log.TraceLevel) + if env.IsProd() { + log.SetLevel(log.InfoLevel) + environment = "production" + log.SetFormatter(&log.JSONFormatter{}) // simpler to query but harder to parse in the console + } + + if sentryDSN := os.Getenv("SENTRY_DSN"); sentryDSN != "" { + if err := sentry.Init(sentry.ClientOptions{ + Dsn: sentryDSN, + AttachStacktrace: true, + Release: Version, + Dist: Version, // see https://github.com/getsentry/sentry-react-native/issues/516 why this is equal + Environment: environment, + }); err != nil { + log.WithError(err).Error("Sentry initialization failed") + } + log.AddHook(sentryhook.New([]log.Level{log.PanicLevel, log.FatalLevel, log.ErrorLevel, log.WarnLevel})) + } else { + log.Info("continuing without sentry") + } +}