Skip to content

Commit

Permalink
Merge: SQL
Browse files Browse the repository at this point in the history
![1dan1m](https://cloud.githubusercontent.com/assets/1444825/19865386/650afce4-9f72-11e6-8e49-5152e7f5f2ed.jpg)

Big PR here, this should make the transition from a MongoDB model to the famed SQL model.
The code base being large, there might be some parts of the application that might break, but from the last checks I did, most of the app should work.
Some parts, like achievements may need a bit of an overhaul to make it production-ready, but the base is here.

Note: I know the login redirect is semi-broken, I'll check to fix it, in the meantime, you are more than encouraged to take a look at the code :)

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/morriar/missions/158)
<!-- Reviewable:end -->

Pull-Request: #158
Reviewed-by: Jean Privat <[email protected]>
Reviewed-by: Alexandre Terrasa <[email protected]>
Reviewed-by: Istvan SZALAÏ <[email protected]>
  • Loading branch information
Jenkins Gresil committed Nov 2, 2016
2 parents 9856192 + 0d78da0 commit 8588183
Show file tree
Hide file tree
Showing 47 changed files with 2,536 additions and 985 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
FROM nitlang/nit

# Needed for nitcorn and to build mongo-c-driver
RUN apt-get update && apt-get install -y libevent-dev libssl-dev libsasl2-dev libcurl4-openssl-dev file
RUN apt-get update && apt-get install -y libevent-dev libssl-dev libsasl2-dev libcurl4-openssl-dev file libsqlite3-dev sqlite3

# Install mongo-c-driver manually since it is not available in Debian/jessie
RUN curl -L https://github.com/mongodb/mongo-c-driver/releases/download/1.4.0/mongo-c-driver-1.4.0.tar.gz -o mongo-c-driver-1.4.0.tar.gz \
Expand Down
5 changes: 4 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,13 @@ bin/db_loader:
nitserial src/db_loader.nit -o src/db_loader_serial.nit
nitc src/db_loader.nit -m src/db_loader_serial.nit -o bin/db_loader

populate: bin/db_loader
populate: bin/db_loader init_db
# There are levels to this... try: `make populate level=2`
bin/db_loader $(level)

init_db:
sqlite3 Missions < init.sql

run:
bin/app --auth shib

Expand Down
210 changes: 210 additions & 0 deletions init.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
DROP TABLE IF EXISTS players;
DROP TABLE IF EXISTS friends;
DROP TABLE IF EXISTS category;
DROP TABLE IF EXISTS tracks;
DROP TABLE IF EXISTS missions;
DROP TABLE IF EXISTS mission_dependencies;
DROP TABLE IF EXISTS testcases;
DROP TABLE IF EXISTS stars;
DROP TABLE IF EXISTS track_status;
DROP TABLE IF EXISTS mission_status;
DROP TABLE IF EXISTS star_status;
DROP TABLE IF EXISTS events;
DROP TABLE IF EXISTS submissions;
DROP TABLE IF EXISTS friend_events;
DROP TABLE IF EXISTS achievements;
DROP TABLE IF EXISTS notifications;
DROP TABLE IF EXISTS achievement_unlocks;
DROP TABLE IF EXISTS languages;
DROP TABLE IF EXISTS track_languages;
DROP TABLE IF EXISTS mission_languages;
DROP TABLE IF EXISTS track_statuses;
DROP TABLE IF EXISTS star_results;


CREATE TABLE players(
id INTEGER PRIMARY KEY AUTOINCREMENT,
slug TEXT UNIQUE NOT NULL,
name TEXT DEFAULT "",
email TEXT DEFAULT "",
avatar_url TEXT DEFAULT "",
date_joined INTEGER NOT NULL
);

CREATE TABLE friends(
player_id1 INTEGER,
player_id2 INTEGER,

PRIMARY KEY(player_id1, player_id2),
FOREIGN KEY(player_id1) REFERENCES players(id),
FOREIGN KEY(player_id2) REFERENCES players(id)
);

CREATE TABLE languages(
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT
);

CREATE TABLE tracks(
id INTEGER PRIMARY KEY AUTOINCREMENT,
slug TEXT UNIQUE NOT NULL,
title TEXT NOT NULL,
description TEXT DEFAULT "",
path TEXT
);

CREATE TABLE track_languages(
track_id INTEGER,
language_id INTEGER,

PRIMARY KEY(track_id, language_id),
FOREIGN KEY(track_id) REFERENCES tracks(id),
FOREIGN KEY(language_id) REFERENCES languages(id)
);

CREATE TABLE track_statuses(
track_id INTEGER,
player_id INTEGER,
status INTEGER,

PRIMARY KEY(track_id, player_id),
FOREIGN KEY(track_id) REFERENCES tracks(id),
FOREIGN KEY(player_id) REFERENCES players(id)
);

CREATE TABLE missions(
id INTEGER PRIMARY KEY AUTOINCREMENT,
slug TEXT UNIQUE NOT NULL,
title TEXT NOT NULL,
track_id INTEGER NOT NULL,
description TEXT NOT NULL,
reward INTEGER DEFAULT 0,
path TEXT,

FOREIGN KEY(track_id) REFERENCES tracks(id)
);

CREATE TABLE mission_languages(
mission_id INTEGER,
language_id INTEGER,

PRIMARY KEY(mission_id, language_id),
FOREIGN KEY (mission_id) REFERENCES missions(id),
FOREIGN KEY (language_id) REFERENCES languages(id)
);

CREATE TABLE mission_dependencies(
mission_id INTEGER NOT NULL,
parent_id INTEGER NOT NULL,
PRIMARY KEY (mission_id, parent_id),

FOREIGN KEY(mission_id) REFERENCES missions(id),
FOREIGN KEY(parent_id) REFERENCES missions(id)
);

CREATE TABLE testcases(
id INTEGER PRIMARY KEY AUTOINCREMENT,
mission_id INTEGER NOT NULL,
root_uri TEXT NOT NULL,

FOREIGN KEY(mission_id) REFERENCES missions(id)
);

CREATE TABLE stars(
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
mission_id INTEGER NOT NULL,
score INTEGER DEFAULT 0,
reward INTEGER DEFAULT 0,
type_id INTEGER NOT NULL,

FOREIGN KEY(mission_id) REFERENCES missions(id)
);

CREATE TABLE mission_status(
mission_id INTEGER,
player_id INTEGER,
status INTEGER NOT NULL,
PRIMARY KEY(mission_id, player_id),

FOREIGN KEY(mission_id) REFERENCES missions(id),
FOREIGN KEY(player_id) REFERENCES players(id)
);

CREATE TABLE star_status(
star_id INTEGER,
player_id INTEGER,
status BOOLEAN DEFAULT FALSE,
PRIMARY KEY(star_id, player_id),

FOREIGN KEY(star_id) REFERENCES stars(id),
FOREIGN KEY(player_id) REFERENCES players(id)
);

CREATE TABLE events(
id INTEGER PRIMARY KEY AUTOINCREMENT,
datetime INTEGER NOT NULL
);

CREATE TABLE submissions(
event_id INTEGER PRIMARY KEY,
player_id INTEGER NOT NULL,
mission_id TEXT NOT NULL,
workspace_path TEXT,
status INTEGER DEFAULT 1,

FOREIGN KEY(event_id) REFERENCES events(id),
FOREIGN KEY(player_id) REFERENCES players(id),
FOREIGN KEY(mission_id) REFERENCES missions(id)
);

CREATE TABLE friend_events(
event_id INTEGER PRIMARY KEY,
player_id1 INTEGER NOT NULL,
player_id2 INTEGER NOT NULL,
status INTEGER DEFAULT 0,

FOREIGN KEY(event_id) REFERENCES events(id),
FOREIGN KEY(player_id1) REFERENCES players(id),
FOREIGN KEY(player_id2) REFERENCES players(id)
);

CREATE TABLE achievements(
id INTEGER PRIMARY KEY AUTOINCREMENT,
slug TEXT UNIQUE NOT NULL,
title TEXT NOT NULL,
description TEXT,
reward INTEGER DEFAULT 0
);

CREATE TABLE achievement_unlocks(
event_id INTEGER PRIMARY KEY,
achievement_id INTEGER,
player_id INTEGER,

FOREIGN KEY(event_id) REFERENCES events(id),
FOREIGN KEY(player_id) REFERENCES players(id),
FOREIGN KEY(achievement_id) REFERENCES achievements(id)
);

CREATE TABLE notifications(
id INTEGER PRIMARY KEY AUTOINCREMENT,
event_id INTEGER NOT NULL,
player_id INTEGER NOT NULL,
object TEXT NOT NULL,
body TEXT DEFAULT "",
read BOOLEAN DEFAULT FALSE,

FOREIGN KEY(event_id) REFERENCES events(id),
FOREIGN KEY(player_id) REFERENCES players(id)
);

CREATE TABLE star_results(
id INTEGER PRIMARY KEY AUTOINCREMENT,
submission_id INTEGER NOT NULL,
star_id INTEGER NOT NULL,
score INTEGER NOT NULL,

FOREIGN KEY(submission_id) REFERENCES submissions(event_id),
FOREIGN KEY(star_id) REFERENCES stars(id)
);
6 changes: 3 additions & 3 deletions src/api/api_achievements.nit
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class APIAchievements
super APIHandler

redef fun get(req, res) do
res.json new JsonArray.from(config.achievements.group_achievements)
res.json new JsonArray.from(req.ctx.all_achievements)
end
end

Expand All @@ -43,7 +43,7 @@ class APIAchievement
res.api_error("Missing URI param `aid`", 400)
return null
end
var achievement = config.achievements.find_by_key(aid)
var achievement = req.ctx.achievement_by_slug(aid)
if achievement == null then
res.api_error("Achievement `{aid}` not found", 404)
return null
Expand All @@ -64,6 +64,6 @@ class APIAchievementPlayers
redef fun get(req, res) do
var achievement = get_achievement(req, res)
if achievement == null then return
res.json new JsonArray.from(achievement.players(config))
res.json new JsonArray.from(achievement.players)
end
end
17 changes: 11 additions & 6 deletions src/api/api_auth.nit
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ class SessionRefresh
if session == null then return
var player = session.player
if player == null then return
session.player = config.players.find_by_id(player.id)
session.player = req.ctx.player_by_id(player.id)
end
end

Expand Down Expand Up @@ -117,8 +117,14 @@ abstract class AuthLogin
# Helper method to use when a new account is created.
fun register_new_player(player: Player)
do
player.add_achievement(config, new FirstLoginAchievement(player))
config.players.save player
var ctx = player.context
var first_login = ctx.achievement_by_slug("hello_world")
if first_login == null then
first_login = new FirstLoginAchievement(ctx)
first_login.commit
end
player.add_achievement(first_login)
player.commit
end

# Redirect to the `next` page.
Expand Down Expand Up @@ -149,6 +155,7 @@ class AuthHandler
res.api_error("Unauthorized", 403)
return null
end
player.context = req.ctx
return player
end
end
Expand All @@ -175,11 +182,9 @@ end
class FirstLoginAchievement
super Achievement
serialize
autoinit player
autoinit(context)

redef var key = "first_login"
redef var title = "Hello World!"
redef var desc = "Login into the mission board for the first time."
redef var reward = 10
redef var icon = "log-in"
end
7 changes: 3 additions & 4 deletions src/api/api_auth_github.nit
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,10 @@ class MissionsGithubOAuthCallBack
var user = session.user
if user == null then return
var id = user.login
var player = config.players.find_by_id(id)
var player = req.ctx.player_by_slug(id)
if player == null then
player = new Player(id)
player.name = user.login
player.avatar_url = user.avatar_url
var avatar = user.avatar_url or else ""
player = new Player(req.ctx, id, user.login, "", avatar)
register_new_player(player)
end
session.player = player
Expand Down
2 changes: 1 addition & 1 deletion src/api/api_auth_rand.nit
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class RandLogin
if session == null then return
var id = req.get_args.get_or_null("id")
if id == null then return
var player = config.players.find_by_id(id)
var player = req.ctx.player_by_slug(id)
if player == null then return
session.player = player
res.redirect "/player"
Expand Down
9 changes: 4 additions & 5 deletions src/api/api_auth_shibuqam.nit
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,11 @@ class ShibCallback
end

# Get the player (a new or an old one)
var id = user.id
var player = config.players.find_by_id(id)
var slug = user.id
var ctx = req.ctx
var player = ctx.player_by_slug(slug)
if player == null then
player = new Player(id)
player.name = user.display_name
player.avatar_url = user.avatar
player = new Player(ctx, slug, user.display_name, user.email, user.avatar)
register_new_player(player)
end
session.player = player
Expand Down
Loading

0 comments on commit 8588183

Please sign in to comment.