In user list, show icons with flag_showhidden permission
[ais.git] / bin / djais / models.py
1 # -*- coding: utf-8 -*-
2
3 from __future__ import division
4 import os, os.path
5 from datetime import datetime
6 from django.db import models
7 from django.contrib.auth.models import get_hexdigest
8 from django.utils import html
9
10 from ais.common import Nmea, mmsi_to_strmmsi, nice_timedelta_str
11 from ais import proc
12 from ais.jobrunner import make_unique_job_id
13
14 class UserMessageCategory(models.Model):
15     id = models.CharField(max_length=10, primary_key=True)
16     class Meta:
17         db_table = u'user_message_category'
18
19 class UserMessage(models.Model):
20     id = models.AutoField(primary_key=True)
21     user = models.ForeignKey('User')
22     category = models.ForeignKey(UserMessageCategory, db_column='user_message_category_id')
23     txt = models.TextField()
24     class Meta:
25         db_table = u'user_message'
26
27 class User(models.Model):
28     id = models.AutoField(primary_key=True)
29     login = models.CharField(max_length=16, unique=True)
30     password_hash = models.CharField(max_length=75)
31     name = models.CharField(max_length=50)
32     email = models.EmailField()
33     father = models.ForeignKey('User')
34     creation_datetime = models.DateTimeField(auto_now_add=True)
35     phone = models.CharField(max_length=20, blank=True)
36     access_datetime = models.DateTimeField(blank=True, null=True)
37     flag_allowhidden = models.BooleanField(default=False)
38     class Meta:
39         db_table = u'user'
40         ordering = ('id',)
41
42     def __unicode__(self):
43         return self.login
44
45     def set_password(self, raw_password):
46         import random
47         algo = 'sha1'
48         salt = get_hexdigest(algo, str(random.random()), str(random.random()))[:5]
49         hsh = get_hexdigest(algo, salt, raw_password)
50         self.password_hash = '%s$%s$%s' % (algo, salt, hsh)
51         self.info('Password changed') # FIXME
52
53     def check_password(self, raw_password):
54         password_hash = self.password_hash
55         if not password_hash:
56             return False
57         algo, salt, hsh = password_hash.split('$')
58         return hsh == get_hexdigest(algo, salt, raw_password)
59
60
61     def update_access_datetime(self):
62         self.access_datetime = datetime.utcnow()
63         self.save()
64
65     def get_and_delete_messages(self):
66         return None
67
68     def is_admin_by(self, user_id):
69         if self.id == user_id:
70             return True
71         if self.father_id is None:
72             return False
73         return self.father.is_admin_by(user_id)
74
75     def get_messages(self):
76         messages = UserMessage.objects.filter(user__id = self.id)
77         messages_dict = \
78             [ {'category': message.category, \
79                'txt': message.txt} \
80             for message in messages \
81             ]
82         messages.delete()
83         return messages_dict
84     
85     def info(self, message):
86         UserMessage(user_id = self.id, category_id=u'info', txt=html.escape(message)).save()
87
88     def error(self, message):
89         UserMessage(user_id = self.id, category_id=u'error', txt=html.escape(message)).save()
90
91     def check_sandbox_access(self, source_user=None):
92         SANDBOX_FLEET = 1
93         try:
94             FleetUser.objects.get(fleet = SANDBOX_FLEET, user = self)
95         except FleetUser.DoesNotExist:
96             fu = FleetUser()
97             fu.user_id = self.id
98             fu.fleet_id = SANDBOX_FLEET
99             fu.save()
100             if source_user:
101                 source_user.info("%s was granted access to 'sandbox' fleet" % self.login)
102
103     def fleets_count(self):
104         return FleetUser.objects.filter(user=self.id).count()
105
106
107 class Vessel(models.Model):
108     mmsi = models.IntegerField(primary_key=True)
109     name = models.CharField(max_length=20)
110     imo = models.IntegerField()
111     callsign = models.CharField(max_length=7)
112     type = models.IntegerField(default=0)
113     destination = models.CharField(max_length=20, blank=True, null=True)
114     updated = models.DateTimeField()
115     source = models.CharField(max_length=8)
116     dim_bow = models.IntegerField(default=0)
117     dim_stern = models.IntegerField(default=0)
118     dim_port = models.IntegerField(default=0)
119     dim_starboard = models.IntegerField(default=0)
120     eta = models.CharField(max_length=8, default='00002460') # format MMDDhhmm
121     class Meta:
122         db_table = u'vessel'
123     def __unicode__(self):
124         return unicode(self.mmsi) # FIXME
125     def get_last_nmea(self):
126         strmmsi = mmsi_to_strmmsi(self.mmsi)
127         return Nmea.new_from_lastinfo(strmmsi)
128
129
130 class Fleet(models.Model):
131     id = models.AutoField(primary_key=True)
132     name = models.CharField(max_length=50)
133     vessel = models.ManyToManyField(Vessel, through='FleetVessel')
134     description = models.TextField()
135     class Meta:
136         db_table = u'fleet'
137     def __unicode__(self):
138         return self.name
139     def vessel_count(self):
140         return FleetVessel.objects.filter(fleet=self.id).count()
141     def user_count(self):
142         return FleetUser.objects.filter(fleet=self.id).count()
143     def job_count(self):
144         if os.path.exists('/var/lib/ais/cron/fleets/%s.cron' % self.name):
145             return 1
146         else:
147             return 0
148
149 class FleetUser(models.Model):
150     id = models.AutoField(primary_key=True)
151     fleet = models.ForeignKey(Fleet) #, db_column='fleet_id', to_field='id')
152     user = models.ForeignKey(User)
153     class Meta:
154         db_table = u'fleet_user'
155
156 class FleetVessel(models.Model):
157     id = models.AutoField(primary_key=True)
158     fleet = models.ForeignKey(Fleet, db_column='fleet_id', to_field='id')
159     vessel = models.ForeignKey(Vessel, db_column='mmsi', to_field='mmsi')
160     class Meta:
161         db_table = u'fleet_vessel'
162     
163 ## manual input source
164 #class MiSource(models.Model):
165 #    id = models.IntegerField(primary_key=True)
166 #    userid = models.IntegerField()
167 #    name = models.TextField(unique=True)
168 #    class Meta:
169 #        db_table = u'mi_source'
170 #
171 ## manual input vessel
172 #class MiVessel(models.Model):
173 #    mmsi_txt = models.TextField(primary_key=True) # This field type is a guess.
174 #    class Meta:
175 #        db_table = u'mi_vessel'
176
177
178 # Plane plotter
179 #class Ppuser(models.Model):
180 #    usr = models.TextField(primary_key=True) # This field type is a guess.
181 #    lat = models.FloatField()
182 #    lon = models.FloatField()
183 #    class Meta:
184 #        db_table = u'ppuser'
185 #
186 #class Plane(models.Model):
187 #    flight = models.CharField(max_length=8)
188 #    reg = models.CharField(max_length=8)
189 #    ads = models.CharField(max_length=8)
190 #    type = models.CharField(max_length=4)
191 #    usr = models.TextField() # This field type is a guess.
192 #    updated = models.DateTimeField()
193 #    class Meta:
194 #        db_table = u'plane'
195
196
197
198 class News(models.Model):
199     id = models.AutoField(primary_key=True)
200     created = models.DateTimeField()
201     updated = models.DateTimeField()
202     title = models.TextField()
203     txt = models.TextField()
204     class Meta:
205         db_table = u'news'
206
207
208 class Job(models.Model):
209     id = models.CharField(primary_key=True, max_length=8, default=make_unique_job_id)
210     user = models.ForeignKey(User)
211     queue_time = models.DateTimeField() #auto_now_add=True) is buggy, not GMT
212     start_time = models.DateTimeField(blank=True, null=True)
213     finish_time = models.DateTimeField(blank=True, null=True)
214     command = models.TextField()
215     friendly_filename = models.CharField(max_length=255)
216     pid = models.IntegerField(blank=True, null=True)
217     result = models.IntegerField(blank=True, null=True)
218     archive_time = models.DateTimeField(blank=True, null=True)
219     notify = models.CharField(max_length=1, blank=True, null=True)
220
221     def queue_rank(self):
222         return Job.objects.filter(queue_time__lt=self.queue_time).filter(start_time__isnull=True).count() + 1
223
224     @staticmethod
225     def queue_size():
226         return Job.objects.filter(start_time__isnull=True).count()
227
228     def process_time(self):
229         dt = self.finish_time - self.start_time
230         return nice_timedelta_str(dt)
231
232     def running_time(self):
233         dt = datetime.utcnow() - self.start_time
234         return nice_timedelta_str(dt)
235
236     def get_stats(self):
237         try:
238             return proc.Stat(self.pid)
239         except:
240             return
241     
242     def get_sucess_size(self):
243         extension = os.path.splitext(self.friendly_filename)[-1]
244         filename = '/var/lib/ais/jobs/%s%s' % (self.id, extension)
245         return os.path.getsize(filename)
246
247     def get_log_size(self):
248         filename = '/var/lib/ais/jobs/%s.log' % self.id
249         try:
250             return os.path.getsize(filename)
251         except OSError, err:
252             if err.errno == 2:
253                 return 0
254             raise
255
256     class Meta:
257         db_table = u'job'
258         ordering = ('queue_time',)