bb461931f8f63ee51b6ad8ff31ed9a41a4f1e73e
[nit.git] / contrib / tnitter / src / model.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2014 Alexis Laferrière <alexis.laf@xymus.net>
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16
17 # Data and DB model of Tnitter
18 module model
19
20 import sqlite3
21 import md5
22
23 # The Tnitter database
24 class DB
25 super Sqlite3DB
26
27 redef init open(path)
28 do
29 super
30 create_tables
31 end
32
33 # Create the needed tables
34 fun create_tables
35 do
36 assert create_table("IF NOT EXISTS users (user TEXT PRIMARY KEY, pass TEXT)") else
37 print error or else "?"
38 end
39
40 assert create_table("IF NOT EXISTS posts (user TEXT, text TEXT, posted DATETIME DEFAULT CURRENT_TIMESTAMP)") else
41 print error or else "?"
42 end
43 end
44
45 # Check if the login credentials are valid
46 #
47 # If valid, returns the username at database creation time. Otherwise returns `null`.
48 fun check_login(user, pass: String): nullable String
49 do
50 var stmt = select("user FROM users WHERE lower({user.to_sql_string}) = lower(user) " +
51 "AND {pass.tnitter_hash.to_sql_string} = pass")
52 assert stmt != null else print error or else "?"
53
54 for row in stmt do return row[0].to_s
55 return null
56 end
57
58 # Try to sign up a new user, return `true` on success
59 fun sign_up(user, pass: String): Bool
60 do
61 # Check if already in user
62 var stmt = select("user FROM users WHERE lower({user.to_sql_string}) = lower(user)")
63 assert stmt != null else print error or else "?"
64
65 if not stmt.iterator.to_a.is_empty then return false
66
67 # Insert intro BD
68 assert insert("INTO users(user, pass) VALUES ({user.to_sql_string}, {pass.tnitter_hash.to_sql_string})") else
69 print error or else "?"
70 end
71
72 return true
73 end
74
75 # Tnit something
76 fun post(user, text: String)
77 do
78 assert insert("INTO posts(user, text) VALUES ({user.to_sql_string}, {text.to_sql_string})") else
79 print error or else "?"
80 end
81 end
82
83 # Get the latest tnits
84 fun latest_posts(count: Int): Array[Post]
85 do
86 var stmt = select("user, text FROM posts ORDER BY datetime(posted) DESC LIMIT {count}")
87 assert stmt != null else print error or else "?"
88
89 var posts = new Array[Post]
90 for row in stmt do posts.add new Post(row[0].to_s, row[1].to_s)
91
92 return posts
93 end
94 end
95
96 # A single post (or Tnit)
97 class Post
98 # The author
99 var user: String
100
101 # Tnit content
102 var text: String
103 end
104
105 redef class String
106 # Hash passwords for Tnitter
107 fun tnitter_hash: String do return (self+salt).md5
108 end
109
110 # Salt used on passwords
111 #
112 # Can be redefed by user modules
113 fun salt: String do return "tnitter is cool"