Completed
Push — master ( 5850a4...5772bc )
by Andrew
01:00
created

IpAddress.info()   A

Complexity

Conditions 2

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
1
import datetime
2
import time
3
from enum import Enum
4
from time import mktime
5
6
from django.contrib.auth.models import BaseUserManager, AbstractBaseUser
7
from django.db import models
8
from django.db.models import CharField, DateField, FileField, BooleanField
9
10
from chat.log_filters import id_generator
11
from chat.settings import GENDERS, DEFAULT_PROFILE_ID, JS_CONSOLE_LOGS
12
13
14
def get_random_path(instance, filename):
15
	"""
16
	:param filename base string for generated name
17
	:return: a unique string filename
18
	"""
19
	return "{}_{}".format(id_generator(8), filename)
20
21
22
class User(AbstractBaseUser):
23
	def get_short_name(self):
24
		return self.username
25
26
	def get_full_name(self):
27
		return self.username
28
29
	@property
30
	def is_staff(self):
31
		# every registered user can edit database
32
		return self.pk == DEFAULT_PROFILE_ID
33
34
	def has_perm(self, perm, obj=None):
35
		return self.is_staff
36
37
	def has_perms(self, perm, obj=None):
38
		return True
39
40
	def has_module_perms(self, app_label):
41
		return self.is_staff
42
43
	USERNAME_FIELD = 'username'
44
	username = CharField(max_length=30, null=False, unique=True)
45
46
	# specifies auth, create email, etc methods
47
	objects = BaseUserManager()
48
49
	# ISO/IEC 5218 1 male, 2 - female
50
	sex = models.SmallIntegerField(null=False, default=0)
51
52
	@property
53
	def sex_str(self):
54
		return GENDERS[self.sex]
55
56
	@sex_str.setter
57
	def sex_str(self, sex):
58
		if sex == 'Male':
59
			self.sex = 1
60
		elif sex == 'Female':
61
			self.sex = 2
62
		else:
63
			self.sex = 0
64
65
66
class Verification(models.Model):
67
68
	class TypeChoices(Enum):
69
		register = 'r'
70
		password = 'p'
71
72
	# a - account activation, r - recover
73
	type = models.CharField(null=False, max_length=1)
74
	token = models.CharField(max_length=17, null=False, default=id_generator)
75
	user = models.ForeignKey(User, null=False)
76
	time = models.DateTimeField(default=datetime.datetime.now)
77
	verified = BooleanField(default=False)
78
79
	@property
80
	def type_enum(self):
81
		return self.TypeChoices(self.type)
82
83
	@type_enum.setter
84
	def type_enum(self, p_type):
85
		"""
86
		:type p_type: Verification.TypeChoices
87
		"""
88
		self.type = p_type.value
89
90
91
class UserProfile(User):
92
	name = CharField(max_length=30, null=True)
93
94
	surname = CharField(max_length=30, null=True)
95
	email = models.EmailField(null=True, unique=True, blank=True)
96
	city = CharField(max_length=50, null=True)
97
98
	birthday = DateField(null=True)
99
	contacts = CharField(max_length=100, null=True)
100
	# fileField + <img instead of ImageField (removes preview link)
101
	photo = FileField(upload_to=get_random_path, null=True)
102
	suggestions = BooleanField(null=False, default=True)
103
	notifications = BooleanField(null=False, default=True)
104
	logs = BooleanField(null=False, default=JS_CONSOLE_LOGS)
105
	# TODO, save theme in profile? theme_name = CharField(max_length=16, null=True)
106
107
	email_verification = models.ForeignKey(Verification, null=True)
108
109
	def save(self, *args, **kwargs):
110
		"""
111
		http://stackoverflow.com/questions/15422606/django-model-email-field-unique-if-not-null-blank
112
		"""
113
		if self.email is not None:
114
			self.email.lower().strip()  # Hopefully reduces junk to ""
115
			if self.email == "":
116
				self.email = None
117
		super(UserProfile, self).save(*args, **kwargs)
118
119
120
class Room(models.Model):
121
	name = CharField(max_length=16, null=True)
122
	users = models.ManyToManyField(User, related_name='rooms', through='RoomUsers')
123
	disabled = BooleanField(default=False, null=False)
124
125
	@property
126
	def is_private(self):
127
		return self.name is None
128
129
130
def get_milliseconds(dt=None):
131
	if dt is None:
132
		return int(time.time()*1000)
133
	if dt.time.timestamp:
134
		return int(dt.time.timestamp()*1000)
135
	else:
136
		return mktime(dt.time.timetuple()) * 1000 + int(dt.time.microsecond / 1000)
137
138
139
class Message(models.Model):
140
	"""
141
	Contains all public messages
142
	"""
143
	sender = models.ForeignKey(User, related_name='sender')
144
	room = models.ForeignKey(Room, null=True)
145
	# DateField.auto_now
146
	time = models.BigIntegerField(default=get_milliseconds)
147
	content = models.TextField(null=True)
148
	img = FileField(upload_to=get_random_path, null=True)
149
	deleted = BooleanField(default=False)
150
151
152
class RoomUsers(models.Model):
153
	room = models.ForeignKey(Room, null=False)
154
	user = models.ForeignKey(User, null=False)
155
	last_read_message = models.ForeignKey(Message, null=True)
156
157
	class Meta:  # pylint: disable=C1001
158
		unique_together = ("user", "room")
159
		db_table = ''.join((User._meta.app_label, '_room_users'))
160
161
162
class Issue(models.Model):
163
	content = models.TextField(null=False)  # unique = true, but mysql doesnt allow unique fields for unspecified size
164
165
	def __str__(self):
166
		return self.content
167
168
169
class IssueDetails(models.Model):
170
	sender = models.ForeignKey(User, null=False	)
171
	browser = models.CharField(null=False, max_length=32)
172
	time = models.DateField(default=datetime.datetime.now, blank=True)
173
	issue = models.ForeignKey(Issue, related_name='issue')
174
	log = models.TextField(null=True)
175
176
	class Meta:  # pylint: disable=C1001
177
		db_table = ''.join((User._meta.app_label, '_issue_detail'))
178
179
180
class IpAddress(models.Model):
181
	ip = models.CharField(null=False, max_length=32, unique=True)
182
	isp = models.CharField(null=True, max_length=32)
183
	country_code = models.CharField(null=True, max_length=16)
184
	country = models.CharField(null=True, max_length=32)
185
	region = models.CharField(null=True, max_length=32)
186
	city = models.CharField(null=True, max_length=32)
187
188
	def __str__(self):
189
		return self.ip
190
191
	@property
192
	def info(self):
193
		if self.country is not None:
194
			return "IP: {} {} {} {} ({})".format(self.ip, self.country, self.region, self.city, self.isp)
195
		else:
196
			return str(self)
197
198
	class Meta:  # pylint: disable=C1001
199
		db_table = ''.join((User._meta.app_label, '_ip_address'))
200
201
202
class UserJoinedInfo(models.Model):
203
	ip = models.ForeignKey(IpAddress, null=True)
204
	user = models.ForeignKey(User, null=True)
205
	time = models.DateField(default=datetime.datetime.now)
206
207
	class Meta:  # pylint: disable=C1001
208
		db_table = ''.join((User._meta.app_label, '_user_joined_info'))
209
		unique_together = ("user", "ip")
210