Removing old style migrations... not in use anymore
[mediagoblin.git] / mediagoblin / db / models.py
1 # GNU MediaGoblin -- federated, autonomous media hosting
2 # Copyright (C) 2011 Free Software Foundation, Inc
3 #
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU Affero General Public License as published by
6 # the Free Software Foundation, either version 3 of the License, or
7 # (at your option) any later version.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU Affero General Public License for more details.
13 #
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
17 import datetime, uuid
18
19 from mongokit import Document
20
21 from mediagoblin import util
22 from mediagoblin.auth import lib as auth_lib
23 from mediagoblin import mg_globals
24 from mediagoblin.db.util import ASCENDING, DESCENDING, ObjectId
25
26 ###################
27 # Custom validators
28 ###################
29
30 ########
31 # Models
32 ########
33
34
35 class User(Document):
36 __collection__ = 'users'
37
38 structure = {
39 'username': unicode,
40 'email': unicode,
41 'created': datetime.datetime,
42 'plugin_data': dict, # plugins can dump stuff here.
43 'pw_hash': unicode,
44 'email_verified': bool,
45 'status': unicode,
46 'verification_key': unicode,
47 'is_admin': bool,
48 'url' : unicode,
49 'bio' : unicode
50 }
51
52 required_fields = ['username', 'created', 'pw_hash', 'email']
53
54 default_values = {
55 'created': datetime.datetime.utcnow,
56 'email_verified': False,
57 'status': u'needs_email_verification',
58 'verification_key': lambda: unicode(uuid.uuid4()),
59 'is_admin': False}
60
61 def check_login(self, password):
62 """
63 See if a user can login with this password
64 """
65 return auth_lib.bcrypt_check_password(
66 password, self['pw_hash'])
67
68
69 class MediaEntry(Document):
70 __collection__ = 'media_entries'
71
72 structure = {
73 'uploader': ObjectId,
74 'title': unicode,
75 'slug': unicode,
76 'created': datetime.datetime,
77 'description': unicode, # May contain markdown/up
78 'description_html': unicode, # May contain plaintext, or HTML
79 'media_type': unicode,
80 'media_data': dict, # extra data relevant to this media_type
81 'plugin_data': dict, # plugins can dump stuff here.
82 'tags': [unicode],
83 'state': unicode,
84
85 # For now let's assume there can only be one main file queued
86 # at a time
87 'queued_media_file': [unicode],
88
89 # A dictionary of logical names to filepaths
90 'media_files': dict,
91
92 # The following should be lists of lists, in appropriate file
93 # record form
94 'attachment_files': list,
95
96 # This one should just be a single file record
97 'thumbnail_file': [unicode]}
98
99 required_fields = [
100 'uploader', 'created', 'media_type', 'slug']
101
102 default_values = {
103 'created': datetime.datetime.utcnow,
104 'state': u'unprocessed'}
105
106 def get_comments(self):
107 return self.db.MediaComment.find({
108 'media_entry': self['_id']}).sort('created', DESCENDING)
109
110 def main_mediafile(self):
111 pass
112
113 def generate_slug(self):
114 self['slug'] = util.slugify(self['title'])
115
116 duplicate = mg_globals.database.media_entries.find_one(
117 {'slug': self['slug']})
118
119 if duplicate:
120 self['slug'] = "%s-%s" % (self['_id'], self['slug'])
121
122 def url_for_self(self, urlgen):
123 """
124 Generate an appropriate url for ourselves
125
126 Use a slug if we have one, else use our '_id'.
127 """
128 uploader = self.uploader()
129
130 if self.get('slug'):
131 return urlgen(
132 'mediagoblin.user_pages.media_home',
133 user=uploader['username'],
134 media=self['slug'])
135 else:
136 return urlgen(
137 'mediagoblin.user_pages.media_home',
138 user=uploader['username'],
139 media=unicode(self['_id']))
140
141 def url_to_prev(self, urlgen):
142 """
143 Provide a url to the previous entry from this user, if there is one
144 """
145 cursor = self.db.MediaEntry.find({'_id' : {"$gt": self['_id']},
146 'uploader': self['uploader'],
147 'state': 'processed'}).sort(
148 '_id', ASCENDING).limit(1)
149 if cursor.count():
150 return urlgen('mediagoblin.user_pages.media_home',
151 user=self.uploader()['username'],
152 media=unicode(cursor[0]['slug']))
153
154 def url_to_next(self, urlgen):
155 """
156 Provide a url to the next entry from this user, if there is one
157 """
158 cursor = self.db.MediaEntry.find({'_id' : {"$lt": self['_id']},
159 'uploader': self['uploader'],
160 'state': 'processed'}).sort(
161 '_id', DESCENDING).limit(1)
162
163 if cursor.count():
164 return urlgen('mediagoblin.user_pages.media_home',
165 user=self.uploader()['username'],
166 media=unicode(cursor[0]['slug']))
167
168 def uploader(self):
169 return self.db.User.find_one({'_id': self['uploader']})
170
171
172 class MediaComment(Document):
173 __collection__ = 'media_comments'
174
175 structure = {
176 'media_entry': ObjectId,
177 'author': ObjectId,
178 'created': datetime.datetime,
179 'content': unicode,
180 'content_html': unicode}
181
182 required_fields = [
183 'media_entry', 'author', 'created', 'content']
184
185 default_values = {
186 'created': datetime.datetime.utcnow}
187
188 def media_entry(self):
189 return self.db.MediaEntry.find_one({'_id': self['media_entry']})
190
191 def author(self):
192 return self.db.User.find_one({'_id': self['author']})
193
194
195 REGISTER_MODELS = [
196 MediaEntry,
197 User,
198 MediaComment]
199
200
201 def register_models(connection):
202 """
203 Register all models in REGISTER_MODELS with this connection.
204 """
205 connection.register(REGISTER_MODELS)
206