adfinis / timed-backend Goto Github PK
View Code? Open in Web Editor NEWDjango API for the Timed application
License: GNU Affero General Public License v3.0
Django API for the Timed application
License: GNU Affero General Public License v3.0
Currently we still have str.format
, this can be replaced with the more readable f-strings
str.format
class Attendance(models.Model):
"""Attendance model.
An attendance is a timespan in which a user was present at work.
Timespan should not be time zone aware hence splitting into date and
from resp. to time fields.
"""
date = models.DateField()
from_time = models.TimeField()
to_time = models.TimeField()
user = models.ForeignKey(
settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="attendances"
)
def __str__(self) -> str:
"""Represent the model as a string."""
return "{}: {} {} - {}".format(
self.user,
self.date.strftime("%Y-%m-%d"),
self.from_time.strftime("%H:%M"),
self.to_time.strftime("%H:%M"),
)
class Attendance(models.Model):
"""Attendance model.
An attendance is a timespan in which a user was present at work.
Timespan should not be time zone aware hence splitting into date and
from resp. to time fields.
"""
date = models.DateField()
from_time = models.TimeField()
to_time = models.TimeField()
user = models.ForeignKey(
settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="attendances"
)
def __str__(self) -> str:
"""Represent the model as a string."""
return f"{self.user}: {self.date.strftime('%Y-%m-%d')} {self.from_time.strftime('%H:%M')} - {self.to_time.strftime('%H:%M')}"
class Attendance(models.Model):
"""Attendance model.
An attendance is a timespan in which a user was present at work.
Timespan should not be time zone aware hence splitting into date and
from resp. to time fields.
"""
date = models.DateField()
from_time = models.TimeField()
to_time = models.TimeField()
user = models.ForeignKey(
settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="attendances"
)
def __str__(self) -> str:
"""Represent the model as a string."""
return f"{self.user}: {self.date:%Y-%m-%d} {self.from_time:%H:%M} - {self.to_time:%H:%M}"
As per 923f8e2 we seem to be using a PostgreSQL version that was EOLed February 13, 2020.
We should upgrade to a version that is not EOL, basically all versions >9.4 are still in support.
See here for the available versions and their support policy: https://www.postgresql.org/support/versioning/
Once updated the Helm chart for timed also needs updating. In fact this issue surfaced during updating/implementing the chart: adfinis/timed-chart#9 (comment)
We should expose application metrics to help us pinpoint performance or other issues.
The way to go seems to be django-prometheus. The Prometheus metrics will integrate nicely with the Kube Prometheus Stack that is available for this on production.
Apart from exposing metrics in the backend we will also want to configure a PodMonitor
to scrape them in the corresponding Helm chart.
PodMonitor
Dep rest_condition
is not needed anymore and can be replaced with new DRF permission operators which got released in DRF 3.9.
As Timed is also affected from issue we will have to wait for 3.9.1 to implement this.
S324:
timed/subscription/admin.py:27:38: S324 Probable use of insecure hash functions in
hashlib
:md5
| 25 | password = self.cleaned_data.get("password") 26 | if password is not None: 27 | self.instance.password = hashlib.md5(password.encode()).hexdigest() | ^^^^^^^^^^^ S324 28 | return super().save(commit=commit) |class CustomerPassword(models.Model): """Password per customer used for login into SySupport portal. Password are only hashed with md5. This model will be obsolete once customer center will go live. """Can this be dropped, respectively ignored and dropped in a separate PR?
Since https://github.com/adfinis/customer-center does existI'm not 100% if this is still in use or not. It looks like it was part of the old SySupport portal and might have been replaced with a proper solution when the portal was migrated to being an Ember based frontend.
If this is in fact the case then we should create an issue to track the codes removal. Maybe @winged or @trowik know if it's still needed?
I'm also not 100% sure, but I'd say it's safe to remove it in another PR.
Originally posted by @trowik in #1049 (comment)
In Django 4.2 there is django.utils.http.content_disposition_header()
which can help us ensure that the headers are RFC 6266 compliant.
response["Content-Disposition"] = f"attachment; filename={name}"
from django.utils.http import content_disposition_header
response["Content-Disposition"] = content_disposition_header(as_attachment=True, filename=name)
I'm not sure if this is the canonical way to call it, but it does add unicode support to the filename and hides some implementation specifics.
I'm not sure if its worth it, so feel free to close this if you don't think it is.
Originally posted by @hairmare in #1072 (comment)
Timed generates notification e-mails such as "Verification of reports". Those mails may lead to bounces in case one has an e-mail auto-responder active (such as out-of-office notifications), replying to a non-existing sender address (such as [email protected]).
To prevent auto responders from replying to notifications, the Auto-Submitted:
mail header should be included in such e-mails.
Quoting RFC 3834:
The purpose of the Auto-Submitted header field is to indicate that the message was originated by an automatic process, or an automatic responder, rather than by a human; and to facilitate automatic filtering of messages from signal paths for which automatically generated messages and automatic responses are not desirable.
[...]
Automatic responses SHOULD NOT be issued in response to any message which contains an Auto-Submitted header field (see below), where that field has any value other than "no".
I hope that I opened this feature request issue on the correct repository, otherwise feel free to move it.
Passing today seems like something we'd want to take a closer look at and refactor in a diff PR.
Originally posted by @hairmare in #1071 (comment)
Currently there is no automation for publishing container images.
i think we should do this all over the place, most modern projects have already switched
Dependabot couldn't authenticate with https://pypi.python.org/simple/.
You can provide authentication details in your Dependabot dashboard by clicking into the account menu (in the top right) and selecting 'Config variables'.
I took a look at your instructions for installation, settings.py and #8
I believe this can be improved.
Further lecture: https://12factor.net/config
You use a single .env
file.
I would define .env
-files for each environment: .env.development
, .env.test
, .env.build
etc.
Each of them contains the configuration settings for each environment.
To avoid repeating the configuration definitions, a .env.base
may be defined, the more specific .env.*
files then define a more specific set of settings.
I would use .env
just to override the configuration settings of the other files (and for production - i.e. there should be no .env.production
).
Also add a .env.template
which contains the required configuration variables to deploy the application, to simplify operations' tasks (when creating the .env.production
).
I would also use dotenv
to load these environment variables.
It would be great if the settings for each environment were kept in classes using django classy settings
.
Then you can define the settings required in production only in the production class (for instance a sentry backend).
This also allows to set defaults per environment (like the secret key, the database host, etc.) in the class - yet I do not recommend to do so and rather keep the settings in the environment specific .env
-file (read further lecture).
We should have users assigned on various objects, to allow some more elaborate permissions and planning functions.
Ideally, I think each assignment should contain a "role" or "type" field to describe the relation (such as "manager", or "resource"). This way, one could be assigned to a project as a resource for planning purposes, or as a manager for permission purposes.
In a first step, only the assignment should be done - the permissions would probably best be done in a separate PR / feature.
Format code with black:
https://github.com/ambv/black
This way #327 can be fixed as well.
See the change log in #244:
Deprecated
list_route
&detail_route
in favor ofaction
decorator withdetail
boolean.
It's called psycopg again and theire is no psycopg3
package.
Afaict Django 4.2 made s ready for this update and it's time.
Create a report and add an estimated remaining effort to it.
It updates the remaining effort of the certain task in the statistics view.
After submitting the report the remaining effort does not update in stats view. But after editing the rem. effort and saving the report again in the timesheet, it will update the values in the stats view.
The attributes are fine in both requests to the backend. I suspect that a the POST
and PATCH
requests have different handling of the remaining effort attribute. Maybe the POST
does not properly trigger the update?
also needs to be updated in references like ci config
The code should provide type hints where they make sense without overloading the code with hard to maintain typing information.
Ruff has ignore-untyped rules that we actived, in several cases satisfying the rules with some simple hints will improve the code base and further aid modern IDEs.
Static files for django admin don't load on the test aks.
Maybe it's an issue with the STATIC_ROOT
not being correct.
Gunicorn PR
We propose to add the possibility to track remaining effort estimates on Timed Tasks while right next to the field where spent time is tracked (to save horizontal space, "Not billable" and "Needs review" would be replaced by icon buttons).
Using this information, we can add the total remaining effort to project tooltips and task tooltips.
Provided that everyone working on a project updates the remaining effort estimates on the tasks they are working on, the project tooltip yields an always up-to-date remaining effort estimate. The "statistics" page of timed can then be extended to show the budget (red dashed line), spent time (blue bar) and remaining effort estimate (shallow red or green bar).
Since the remaining effort estimates are only useful for some projects (flat fee or cost ceiling, medium to large size), we'd add a setting to the "Projects" screen of timed where PMs can activate / deactivate the function on a per-project basis (default setting: deactivated). For projects without activated remaining effort tracking the extra field in the tracking screen would not be displayed.
What goals are to be achieved
Rescheduling reports from one day to another leads to a 500 error on the /api/v1/reports/40
endpoint.
Latest version (rc10)
The logs from the backend container display the following:
backend_1 | Internal Server Error: /api/v1/reports/40
backend_1 | Traceback (most recent call last):
backend_1 | File "/usr/local/lib/python3.9/site-packages/django/core/handlers/exception.py", line 47, in inner
backend_1 | response = get_response(request)
backend_1 | File "/usr/local/lib/python3.9/site-packages/django/core/handlers/base.py", line 181, in _get_response
backend_1 | response = wrapped_callback(request, *callback_args, **callback_kwargs)
backend_1 | File "/usr/local/lib/python3.9/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
backend_1 | return view_func(*args, **kwargs)
backend_1 | File "/usr/local/lib/python3.9/site-packages/rest_framework/viewsets.py", line 125, in view
backend_1 | return self.dispatch(request, *args, **kwargs)
backend_1 | File "/usr/local/lib/python3.9/site-packages/rest_framework/views.py", line 509, in dispatch
backend_1 | response = self.handle_exception(exc)
backend_1 | File "/usr/local/lib/python3.9/site-packages/rest_framework/views.py", line 469, in handle_exception
backend_1 | self.raise_uncaught_exception(exc)
backend_1 | File "/usr/local/lib/python3.9/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
backend_1 | raise exc
backend_1 | File "/usr/local/lib/python3.9/site-packages/rest_framework/views.py", line 506, in dispatch
backend_1 | response = handler(request, *args, **kwargs)
backend_1 | File "/usr/local/lib/python3.9/site-packages/rest_framework/mixins.py", line 82, in partial_update
backend_1 | return self.update(request, *args, **kwargs)
backend_1 | File "/app/timed/tracking/views.py", line 177, in update
backend_1 | tasks.notify_user_rejected_report(instance, request.user)
backend_1 | File "/app/timed/tracking/tasks.py", line 96, in notify_user_rejected_report
backend_1 | _send_notification_emails([user_changes], reviewer, True)
backend_1 | File "/app/timed/tracking/tasks.py", line 42, in _send_notification_emails
backend_1 | connection.send_messages(messages)
backend_1 | File "/usr/local/lib/python3.9/site-packages/django/core/mail/backends/smtp.py", line 102, in send_messages
backend_1 | new_conn_created = self.open()
backend_1 | File "/usr/local/lib/python3.9/site-packages/django/core/mail/backends/smtp.py", line 67, in open
backend_1 | self.connection.starttls(keyfile=self.ssl_keyfile, certfile=self.ssl_certfile)
backend_1 | File "/usr/local/lib/python3.9/smtplib.py", line 771, in starttls
backend_1 | raise SMTPNotSupportedError(
backend_1 | smtplib.SMTPNotSupportedError: STARTTLS extension not supported by server.
backend_1 | 500 PATCH /api/v1/reports/40 (172.24.0.1) 346.06ms
@trowik This seems to be connected to the rejected report feature.
At first I had a Report actually rejected and got this mail:
Some of your reports have been rejected by a reviewer. Please get in contact
with them to clarify the reports. Most likely, you will just need to move
the reports to the correct project / task.
Reviewer: <Actualy Reviewer>
Date: mm/dd/yyyy
Duration: 7:00 (h:mm)
Task: x > y > z
Comment: <comment>
---
Then after i edited the Report i got this mail:
Some of your reports have been rejected by a reviewer. Please get in contact
with them to clarify the reports. Most likely, you will just need to move
the reports to the correct project / task.
Reviewer: <Myself>
Date: mm/dd/yyyy
Duration: 7:00 (h:mm)
Task: x > y > z
Comment: <edited comment>
---
After every edit i got another mail, where I am marked as the reviewer.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.