Passed
Branch master (882bec)
by Markus
02:33
created

chaoswg.models.User.check_password()   A

Complexity

Conditions 1

Size

Total Lines 2
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 2
dl 0
loc 2
rs 10
c 0
b 0
f 0
cc 1
nop 2
1
from datetime import datetime
2
3
from peewee import (CharField, IntegerField, DateTimeField, SmallIntegerField, ForeignKeyField,
4
                    FloatField, DoesNotExist, SqliteDatabase)
5
from playhouse.flask_utils import FlaskDB
6
from werkzeug.security import generate_password_hash, check_password_hash
7
8
db_wrapper = FlaskDB()
0 ignored issues
show
Coding Style Naming introduced by
The name db_wrapper does not conform to the constant naming conventions ((([A-Z_][A-Z0-9_]*)|(__.*__))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
9
10
11
def init_database(app):
12
    db_wrapper._db = SqliteDatabase(app.config['DATABASE'], pragmas=(('journal_mode', 'wal'),))
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like _db was declared protected and should not be accessed from this context.

Prefixing a member variable _ is usually regarded as the equivalent of declaring it with protected visibility that exists in other languages. Consequentially, such a member should only be accessed from the same class or a child class:

class MyParent:
    def __init__(self):
        self._x = 1;
        self.y = 2;

class MyChild(MyParent):
    def some_method(self):
        return self._x    # Ok, since accessed from a child class

class AnotherClass:
    def some_method(self, instance_of_my_child):
        return instance_of_my_child._x   # Would be flagged as AnotherClass is not
                                         # a child class of MyParent
Loading history...
13
    db_wrapper.init_app(app)
14
    return db_wrapper.database
15
16
17
def create_tables():
18
    db_wrapper.database.connect()
19
    db_wrapper.database.create_tables([User, Task, History], safe=True)
20
    db_wrapper.database.close()
21
22
23
def insert_testdata():
24
    pwhash = generate_password_hash('123456')
25
    with db_wrapper.database.atomic():
26
        # User.get_or_create(username='User1', defaults={'password': pwhash})
27
        # User.get_or_create(username='User2', defaults={'password': pwhash})
28
        # User.get_or_create(username='User3', defaults={'password': pwhash})
29
        # User.get_or_create(username='User4', defaults={'password': pwhash})
30
        # User.get_or_create(username='User5', defaults={'password': pwhash})
31
32
        Task.get_or_create(task='Kühlschrankcheck',
33
                           defaults={'base_points': 2, 'time_factor': 0.0, 'state': Task.BACKLOG})
34
        Task.get_or_create(task='Grünabfall',
35
                           defaults={'base_points': 1, 'time_factor': 0.0, 'state': Task.BACKLOG})
36
        Task.get_or_create(task='Fenster putzen',
37
                           defaults={'base_points': 3, 'time_factor': 0.0, 'state': Task.BACKLOG})
38
        Task.get_or_create(task='Ofen reinigen',
39
                           defaults={'base_points': 3, 'time_factor': 0.0, 'state': Task.BACKLOG})
40
        Task.get_or_create(task='Tiefkühler enteisen',
41
                           defaults={'base_points': 8, 'time_factor': 0.0, 'state': Task.BACKLOG})
42
        Task.get_or_create(task='Saugen + Wischen',
43
                           defaults={'base_points': 13, 'time_factor': 0.0, 'state': Task.TODO})
44
        Task.get_or_create(task='großes Bad',
45
                           defaults={'base_points': 8, 'time_factor': 0.0, 'state': Task.TODO})
46
        Task.get_or_create(task='kleines Bad',
47
                           defaults={'base_points': 3, 'time_factor': 0.0, 'state': Task.DONE})
48
        Task.get_or_create(task='Rasen mähen + harken',
49
                           defaults={'base_points': 13, 'time_factor': 0.0, 'state': Task.TODO})
50
        Task.get_or_create(task='Küche putzen',
51
                           defaults={'base_points': 2, 'time_factor': 0.0, 'state': Task.DONE})
52
        Task.get_or_create(task='Abwaschen',
53
                           defaults={'base_points': 2, 'time_factor': 0.0, 'state': Task.DONE})
54
        Task.get_or_create(task='Einkaufen',
55
                           defaults={'base_points': 3, 'time_factor': 0.0, 'state': Task.DONE})
56
        Task.get_or_create(task='Pappe entsorgen',
57
                           defaults={'base_points': 2, 'time_factor': 0.0, 'state': Task.DONE})
58
        Task.get_or_create(task='Müll entsorgen',
59
                           defaults={'base_points': 1, 'time_factor': 0.0, 'state': Task.DONE})
60
        Task.get_or_create(task='Glas wegbringen',
61
                           defaults={'base_points': 2, 'time_factor': 0.0, 'state': Task.DONE})
62
        Task.get_or_create(task='Geschirrspüler ausräumen',
63
                           defaults={'base_points': 2, 'time_factor': 0.0, 'state': Task.DONE})
64
65
66
class ModelBase(db_wrapper.Model):
67
    @classmethod
68
    def get_all(cls):
69
        return list(cls.select().dicts())
70
71
72
class User(ModelBase):
73
    username = CharField(unique=True)
74
    password = CharField()
75
    points = IntegerField(default=0)
76
    last_update = DateTimeField(default=datetime.utcnow)
77
78
    @classmethod
79
    def get_all(cls):
80
        """
81
        without password
82
        :return:
83
        """
84
        return list(cls.select(cls.username, cls.points, cls.last_update).dicts())
85
86
    @classmethod
87
    def get_by_name(cls, username):
88
        try:
89
            return cls.get(cls.username == username)
90
        except DoesNotExist:
91
            return False
92
93
    @classmethod
94
    def get_usernames(cls):
95
        query = cls.select(cls.username)
96
        result = set()
97
        for user in query:
98
            result.add(user.username)
99
        return result
100
101
    def set_password(self, password):
102
        self.password = generate_password_hash(password)
103
104
    def check_password(self, password):
105
        return check_password_hash(self.password, password)
106
107
    # Flask-Login required functions
108
    @property
109
    def is_active(self):
110
        return True
111
112
    @property
113
    def is_authenticated(self):
114
        return True
115
116
    @property
117
    def is_anonymous(self):
118
        return False
119
120
    def get_id(self):
121
        return self.id
122
123
    # Required for administrative interface
124
    def __unicode__(self):
125
        return self.username
126
127
128
class Task(ModelBase):
129
    task = CharField(unique=True)
130
    base_points = SmallIntegerField()
131
    time_factor = FloatField(default=0.0)
132
    state = SmallIntegerField(index=True, default=0)
133
    BACKLOG = 0
134
    TODO = 1
135
    DONE = 2
136
    todo_time = DateTimeField(null=True)
137
    last_done = DateTimeField(null=True)
138
139
    @property
140
    def points(self):
141
        """
142
        Calculate real point value based on time_factor.
143
        :return:
144
        """
145
        now = datetime.utcnow()
146
        # set last_time to now if todo_time is not set.
147
        last_time = now if not self.todo_time else self.todo_time
148
        real_points = self.base_points + (self.time_factor * (now - last_time).days)
149
        return int(real_points)
150
151
    @classmethod
152
    def get_all(cls):
153
        """
154
        Overwrite get_all() method because we want to have active tasks only and
155
        need the property but dicts() doesn't work with it
156
        :return:
157
        """
158
        return list(cls.select().order_by(cls.base_points.desc()))
159
160
    @classmethod
161
    def set_state(cls, task_id, state, user_id):
162
        now = datetime.utcnow()
163
        points_obtained = 0
164
        with db_wrapper.database.atomic():
165
            # update task state and time
166
            task = cls.get(cls.id == task_id)
167
            task.state = state
168
            if state == cls.DONE:
169
                points_obtained = task.points
170
                task.todo_time = None
171
                task.last_done = now
172
            elif state == cls.TODO:
173
                task.todo_time = now
174
            elif state == cls.BACKLOG:
175
                task.todo_time = None
176
            task.save()
177
178
            # update user points if new state is DONE (user got points)
179
            if points_obtained > 0:
180
                User.update(points=User.points + points_obtained, last_update=now).where(
181
                    User.id == user_id).execute()
182
183
                # add to history
184
                History.create(task=task.task, user=user_id, points=points_obtained, time=now)
185
186
    @staticmethod
187
    def do_custom_task(task, points, user_id):
188
        now = datetime.utcnow()
189
        with db_wrapper.database.atomic():
190
            # update user points
191
            User.update(points=User.points + points, last_update=now).where(User.id == user_id).execute()
192
            # add to history
193
            History.create(task=task, user=user_id, points=points, time=now)
194
195
196
class History(ModelBase):
197
    task = CharField()
198
    user = ForeignKeyField(User)
199
    points = SmallIntegerField()
200
    time = DateTimeField(default=datetime.utcnow())
201
202
    @classmethod
203
    def get_user_history(cls, user):
204
        return list(
205
            cls.select(cls.time, cls.task, cls.points)
206
                .join(User, on=(cls.user == User.id))
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation (remove 4 spaces).
Loading history...
207
                .where(User.username == user)
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation (remove 4 spaces).
Loading history...
208
                .order_by(cls.time.desc()).dicts())
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation (remove 4 spaces).
Loading history...
209
210
    @classmethod
211
    def get_full_history(cls):
212
        return list(
213
            cls.select(cls.time, cls.points, User.username)
214
                .join(User, on=(cls.user == User.id))
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation (remove 4 spaces).
Loading history...
215
                .order_by(cls.time.asc()).dicts())
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation (remove 4 spaces).
Loading history...
216