· 7 years ago · Oct 08, 2018, 08:22 PM
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3#
4# Copyright (c) 2011 The Octopus Apps Inc.
5# Licensed under the Apache License, Version 2.0 (the "License")
6#
7# Author: Alejandro M. Bernardis
8# Email: alejandro.m.bernardis at gmail.com
9# Created: May 8, 2012, 6:25:25 PM
10
11import re, datetime
12
13from bson.objectid import ObjectId
14from com.ak.tornado.security import Password, Role, secret_key, activation_key
15from mongoengine import Document, StringField, IntField, URLField, EmailField,\
16 DateTimeField, BooleanField, Q, ReferenceField, CASCADE
17
18#: -- helpers ------------------------------------------------------------------
19
20__all__ = [
21 "User",
22 "LegalAudit",
23 "Location",
24 "DateCompare",
25 "get_date_compare",
26]
27
28#: -- fields -------------------------------------------------------------------
29
30password_exp = re.compile(r"^sha1\$([A-Z0-9]+)", re.IGNORECASE)
31
32class PasswordField(StringField):
33 def __set__(self, instance, value):
34 if value and not password_exp.search(str(value)):
35 value = Password.generate(str(value))
36 StringField.__set__(self, instance, value)
37
38#: -- DateCompare --------------------------------------------------------------
39
40class DateCompare(object):
41 def __init__(self, date=None, date_min=-1, date_max=1):
42 self.date = date or datetime.datetime.now()
43
44 compare_min = datetime.datetime(self.date.year, self.date.month,
45 self.date.day, 23, 59, 59)
46
47 self.min = datetime.timedelta(days=date_min) + compare_min
48
49 compare_max = datetime.datetime(self.date.year, self.date.month,
50 self.date.day, 0, 0, 0)
51
52 self.max = datetime.timedelta(days=date_max) + compare_max
53
54#: -- models -------------------------------------------------------------------
55
56class ControlDocument(Document):
57 meta = {
58 "abstract": True
59 }
60
61 #: fields
62 availabled = BooleanField(default=False)
63 enabled = BooleanField(default=False)
64 created = DateTimeField(default=datetime.datetime.now())
65 modified = DateTimeField(default=datetime.datetime.now())
66
67 #: methods
68 def get_date_compare(self, date=None, date_min=-1, date_max=1):
69 return DateCompare(date, date_min, date_max)
70
71 def _datetime_update(self, key, value=None, update_data=None):
72 try:
73 if not value:
74 value = datetime.datetime.now()
75 if not update_data:
76 update_data = dict()
77 update_data["set__"+key] = value
78 self.update(**update_data)
79 self.reload()
80 return True
81 except:
82 return False
83
84 def set_modified(self, value=None):
85 return self._datetime_update("modified", value)
86
87 def set_modified_with_data(self, update_data, value=None):
88 return self._datetime_update("modified", value, update_data)
89
90 def _status_update(self, key, value=False):
91 try:
92 update_data = dict()
93 update_data["set__"+key] = value
94 return self.set_modified_with_data(update_data)
95 except:
96 return False
97
98 def set_availabled(self, value=False):
99 return self._status_update("availabled", value)
100
101 def set_enabled(self, value=False):
102 return self._status_update("enabled", value)
103
104#: -----------------------------------------------------------------------------
105
106class UserRole(ControlDocument):
107 meta = {
108 "collection": "roles",
109 "indexes": ["name"]
110 }
111
112 #: fields
113 name = StringField(max_length=64, unique=True)
114 permissions = IntField(default=0)
115 level = IntField(default=0)
116 admin = BooleanField(default=False)
117 read = BooleanField(default=False)
118 write = BooleanField(default=False)
119
120 #: methods
121 def allow(self, value):
122 return value >= self.permissions
123
124 def get_role_object(self):
125 role = Role.get_role(self.name)
126 if not role:
127 role = Role(self.name, self.write, self.admin, self.level)
128 return role
129
130#: -----------------------------------------------------------------------------
131
132class UserGender(ControlDocument):
133 meta = {
134 "collection": "genders",
135 "indexes": ["uid"]
136 }
137
138 #: fields
139 uid = IntField(unique=True)
140 name = StringField(max_length=16)
141
142#: -----------------------------------------------------------------------------
143
144class User(ControlDocument):
145 meta = {
146 "collection": "users",
147 "indexes": ["token", "facebook_uid", "username"]
148 }
149
150 #: reference
151 role = ReferenceField(UserRole, CASCADE)
152 gender = ReferenceField(UserGender, CASCADE)
153
154 #: fields
155 token = StringField(max_length=64, unique=True)
156 facebook_uid = StringField(max_length=128, unique=True)
157 username = StringField(max_length=32, required=True, unique=True)
158 password = PasswordField(max_length=128, required=True)
159 email = EmailField(max_length=255, required=True, unique=True)
160 first_name = StringField(max_length=64)
161 middle_name = StringField(max_length=64)
162 last_name = StringField(max_length=64)
163 birthday = DateTimeField()
164 avatar = URLField()
165 secret_question = StringField(max_length=255)
166 secret_answer = StringField(max_length=255)
167 activation_key = StringField(max_length=64)
168 activation_key_expire = DateTimeField()
169 notes = StringField(max_length=500)
170 terms = BooleanField(default=False)
171 policy = BooleanField(default=False)
172 news = BooleanField(default=False)
173 remote_ip = StringField(max_length=64)
174 last_login = DateTimeField(default=datetime.datetime.now())
175
176 #: methods
177 def _set_new_password(self, password=None, update_data=None):
178 try:
179 if not password:
180 password = secret_key(8)
181 if not update_data:
182 update_data = dict()
183 update_data["set__password"] = password
184 return self.set_modified_with_data(update_data)
185 except:
186 return False
187
188 def set_new_password(self, password=None):
189 return self._set_new_password(password)
190
191 def set_activation_key(self, expire_days=1):
192 try:
193 key = activation_key(self.username, self.email)
194 key_expire = datetime.datetime.now()\
195 + datetime.timedelta(days=expire_days)
196 update_data = dict(
197 set__enabled=False,
198 set__activation_key=key,
199 set__activation_key_expire=key_expire)
200 return self.set_modified_with_data(update_data)
201 except:
202 return False
203
204 def set_activation_key_password(self, password=None):
205 update_data = dict(set__enabled=True)
206 return self._set_new_password(password, update_data)
207
208 def validate_activation_key(self, key):
209 try:
210 if not self.activation_key \
211 or not self.activation_key_expire \
212 or self.activation_key_expire < datetime.datetime.today():
213 raise
214 update_data = dict(
215 set__enabled=True,
216 set__activation_key=None,
217 set__activation_key_expire=None)
218 return self.set_modified_with_data(update_data)
219 except:
220 return False
221
222 def set_last_login(self, value=None):
223 return self._datetime_update("last_login", value)
224
225#: -----------------------------------------------------------------------------