Skip to content

Commit df1ae42

Browse files
committed
feat(messages): add messages
1 parent 1bea8c8 commit df1ae42

49 files changed

Lines changed: 3207 additions & 237 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.woodpecker/manifest.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ steps:
1515
event:
1616
- tag
1717
- push
18+
- cron
1819

1920
- name: publish-manifest
2021
image: bash

charts/passport/templates/_helpers.tpl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ rbac.authorization.k8s.io/v1
1616
env:
1717
- name: TZ
1818
value: {{ .Values.time_zone | default "UTC" | quote }}
19+
- name: "DJANGO_SETTINGS_MODULE"
20+
value: "api.settings.production"
1921
- name: VERSION
2022
value: {{ .Chart.AppVersion }}
2123
- name: ADMIN_USERNAME

charts/passport/templates/passport-deployment.yaml renamed to charts/passport/templates/api/passport-api-deployment.yaml

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
apiVersion: apps/v1
22
kind: Deployment
33
metadata:
4-
name: drycc-passport
4+
name: drycc-passport-api
55
labels:
66
heritage: drycc
77
annotations:
88
component.drycc.cc/version: {{ .Values.imageTag }}
99
spec:
10-
replicas: {{ .Values.replicas }}
10+
replicas: {{ .Values.api.replicas }}
1111
strategy:
1212
rollingUpdate:
1313
maxSurge: 1
@@ -16,28 +16,30 @@ spec:
1616
selector:
1717
matchLabels:
1818
app: drycc-passport
19+
component: drycc-passport-api
1920
template:
2021
metadata:
2122
labels: {{- include "common.labels.standard" . | nindent 8 }}
2223
app: drycc-passport
24+
component: drycc-passport-api
2325
spec:
2426
affinity:
25-
podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.podAffinityPreset.type "component" "" "extraMatchLabels" .Values.podAffinityPreset.extraMatchLabels "topologyKey" "" "context" $) | nindent 10 }}
26-
podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.podAntiAffinityPreset.type "component" "" "extraMatchLabels" .Values.podAntiAffinityPreset.extraMatchLabels "topologyKey" "" "context" $) | nindent 10 }}
27-
nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.nodeAffinityPreset.type "key" .Values.nodeAffinityPreset.key "values" .Values.nodeAffinityPreset.values ) | nindent 10 }}
27+
podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.api.podAffinityPreset.type "component" "" "extraMatchLabels" .Values.api.podAffinityPreset.extraMatchLabels "topologyKey" "" "context" $) | nindent 10 }}
28+
podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.api.podAntiAffinityPreset.type "component" "" "extraMatchLabels" .Values.api.podAntiAffinityPreset.extraMatchLabels "topologyKey" "" "context" $) | nindent 10 }}
29+
nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.api.nodeAffinityPreset.type "key" .Values.api.nodeAffinityPreset.key "values" .Values.api.nodeAffinityPreset.values ) | nindent 10 }}
2830
serviceAccount: drycc-passport
2931
initContainers:
30-
- name: drycc-passport-init
32+
- name: drycc-passport-api-init
3133
image: {{.Values.imageRegistry}}/{{.Values.imageOrg}}/python-dev:latest
3234
imagePullPolicy: {{.Values.imagePullPolicy}}
3335
args:
34-
- netcat
35-
- -v
36-
- -u
37-
- $(DRYCC_DATABASE_URL),$(DRYCC_DATABASE_REPLICA_URL)
36+
- netcat
37+
- -v
38+
- -u
39+
- $(DRYCC_DATABASE_URL),$(DRYCC_DATABASE_REPLICA_URL),$(DRYCC_VALKEY_URL)
3840
{{- include "passport.envs" . | indent 8 }}
3941
containers:
40-
- name: drycc-passport
42+
- name: drycc-passport-api
4143
image: {{.Values.imageRegistry}}/{{.Values.imageOrg}}/passport:{{.Values.imageTag}}
4244
imagePullPolicy: {{.Values.imagePullPolicy}}
4345
{{- if .Values.diagnosticMode.enabled }}
@@ -62,7 +64,7 @@ spec:
6264
ports:
6365
- containerPort: 8000
6466
name: http
65-
{{- with index .Values "resources" }}
67+
{{- with index .Values "api" "resources" }}
6668
resources:
6769
{{- toYaml . | nindent 10 }}
6870
{{- end }}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
apiVersion: apps/v1
2+
kind: Deployment
3+
metadata:
4+
name: drycc-passport-celery
5+
labels:
6+
heritage: drycc
7+
annotations:
8+
component.drycc.cc/version: {{ .Values.imageTag }}
9+
spec:
10+
replicas: {{ .Values.celery.replicas }}
11+
strategy:
12+
rollingUpdate:
13+
maxSurge: 1
14+
maxUnavailable: 0
15+
type: RollingUpdate
16+
selector:
17+
matchLabels:
18+
app: drycc-passport
19+
component: drycc-passport-celery
20+
template:
21+
metadata:
22+
labels: {{- include "common.labels.standard" . | nindent 8 }}
23+
app: drycc-passport
24+
component: drycc-passport-celery
25+
spec:
26+
affinity:
27+
podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.celery.podAffinityPreset.type "component" "" "extraMatchLabels" .Values.celery.podAffinityPreset.extraMatchLabels "topologyKey" "" "context" $) | nindent 10 }}
28+
podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.celery.podAntiAffinityPreset.type "component" "" "extraMatchLabels" .Values.celery.podAntiAffinityPreset.extraMatchLabels "topologyKey" "" "context" $) | nindent 10 }}
29+
nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.celery.nodeAffinityPreset.type "key" .Values.celery.nodeAffinityPreset.key "values" .Values.celery.nodeAffinityPreset.values ) | nindent 10 }}
30+
serviceAccount: drycc-passport
31+
initContainers:
32+
- name: drycc-passport-init
33+
image: {{.Values.imageRegistry}}/{{.Values.imageOrg}}/python-dev:latest
34+
imagePullPolicy: {{.Values.imagePullPolicy}}
35+
args:
36+
- netcat
37+
- -v
38+
- -u
39+
- $(DRYCC_DATABASE_URL),$(DRYCC_DATABASE_REPLICA_URL),$(DRYCC_VALKEY_URL)
40+
{{- include "passport.envs" . | indent 8 }}
41+
containers:
42+
- name: drycc-passport-celery
43+
image: {{.Values.imageRegistry}}/{{.Values.imageOrg}}/passport:{{.Values.imageTag}}
44+
imagePullPolicy: {{.Values.imagePullPolicy}}
45+
{{- if .Values.diagnosticMode.enabled }}
46+
command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 10 }}
47+
args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 10 }}
48+
{{- else }}
49+
args:
50+
- celery
51+
- -A
52+
- api
53+
- worker
54+
- -Q
55+
- passport.notifications
56+
- -l
57+
- info
58+
{{- end }}
59+
{{- with index .Values "celery" "resources" }}
60+
resources:
61+
{{- toYaml . | nindent 10 }}
62+
{{- end }}
63+
{{- include "passport.envs" . | indent 8 }}
64+
{{- include "passport.volumeMounts" . | indent 8 }}
65+
{{- include "passport.volumes" . | indent 6 }}

charts/passport/templates/passport-service.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,14 @@ metadata:
77
{{- toYaml . | nindent 4 }}
88
{{- end }}
99
labels:
10+
app: drycc-passport
1011
heritage: drycc
12+
component: drycc-passport-api
1113
spec:
1214
ports:
1315
- name: http
1416
port: 80
1517
targetPort: 8000
1618
selector:
1719
app: drycc-passport
20+
component: drycc-passport-api

charts/passport/values.yaml

Lines changed: 45 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -18,32 +18,52 @@ diagnosticMode:
1818
args:
1919
- infinity
2020

21-
resources: {}
22-
# limits:
23-
# cpu: 200m
24-
# memory: 50Mi
25-
# requests:
26-
# cpu: 100m
27-
# memory: 30Mi
21+
api:
22+
replicas: 1
23+
resources: {}
24+
# limits:
25+
# cpu: 200m
26+
# memory: 50Mi
27+
# requests:
28+
# cpu: 100m
29+
# memory: 30Mi
30+
nodeAffinityPreset:
31+
key: "drycc.cc/node"
32+
type: "soft"
33+
values:
34+
- "true"
35+
podAffinityPreset:
36+
type: ""
37+
extraMatchLabels:
38+
security: "drycc-security"
39+
podAntiAffinityPreset:
40+
type: "soft"
41+
extraMatchLabels:
42+
app: "drycc-passport-api"
2843

29-
nodeAffinityPreset:
30-
key: "drycc.cc/node"
31-
type: "soft"
32-
values:
33-
- "true"
34-
35-
podAffinityPreset:
36-
type: ""
37-
extraMatchLabels:
38-
security: "drycc-security"
39-
40-
podAntiAffinityPreset:
41-
type: "soft"
42-
extraMatchLabels:
43-
app: "drycc-passport"
44-
45-
# Set passport deployment replicas
46-
replicas: 1
44+
celery:
45+
replicas: 1
46+
resources: {}
47+
# limits:
48+
# cpu: 200m
49+
# memory: 50Mi
50+
# requests:
51+
# cpu: 100m
52+
# memory: 30Mi
53+
nodeAffinityPreset:
54+
key: "drycc.cc/node"
55+
type: "soft"
56+
values:
57+
- "true"
58+
podAffinityPreset:
59+
type: ""
60+
extraMatchLabels:
61+
security: "drycc-security"
62+
podAntiAffinityPreset:
63+
type: "soft"
64+
extraMatchLabels:
65+
app: "drycc-passport"
66+
component: "drycc-passport-celery"
4767
## valkeyUrl is will no longer use the built-in valkey component
4868
valkeyUrl: ""
4969
## databaseUrl and databaseReplicaUrl are will no longer use the built-in database component

rootfs/api/__init__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,7 @@
1+
"""
2+
The **api** Django app presents a RESTful web API for interacting with the **drycc** system.
3+
"""
4+
from .settings.celery import app as celery_app
5+
16
__version__ = '1.1.0'
7+
__all__ = ('celery_app',)

rootfs/api/admin.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from django.contrib import admin
22
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
33

4-
from .models import User
4+
from .models import User, Message, MessagePreference
55

66

77
class UserAdmin(BaseUserAdmin):
@@ -13,4 +13,18 @@ class UserAdmin(BaseUserAdmin):
1313
)
1414

1515

16+
class MessageAdmin(admin.ModelAdmin):
17+
list_display = ('id', 'user', 'category', 'title', 'severity', 'is_read', 'created_at')
18+
list_filter = ('category', 'severity', 'is_read', 'created_at')
19+
search_fields = ('title', 'content', 'user__username')
20+
readonly_fields = ('created_at', 'updated_at')
21+
22+
23+
class MessagePreferenceAdmin(admin.ModelAdmin):
24+
list_display = ('user', 'email_alerts', 'push_alerts')
25+
search_fields = ('user__username',)
26+
27+
1628
admin.site.register(User, UserAdmin)
29+
admin.site.register(Message, MessageAdmin)
30+
admin.site.register(MessagePreference, MessagePreferenceAdmin)
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# Generated by Django 5.2.13 on 2026-04-23 03:45
2+
3+
import django.db.models.deletion
4+
from django.conf import settings
5+
from django.db import migrations, models
6+
7+
8+
class Migration(migrations.Migration):
9+
10+
dependencies = [
11+
('api', '0003_application_allowed_origins_and_more'),
12+
]
13+
14+
operations = [
15+
migrations.AlterField(
16+
model_name='application',
17+
name='authorization_grant_type',
18+
field=models.CharField(choices=[('authorization-code', 'Authorization code'), ('urn:ietf:params:oauth:grant-type:device_code', 'Device Code'), ('implicit', 'Implicit'), ('password', 'Resource owner password-based'), ('client-credentials', 'Client credentials'), ('openid-hybrid', 'OpenID connect hybrid')], max_length=44),
19+
),
20+
migrations.CreateModel(
21+
name='Message',
22+
fields=[
23+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
24+
('category', models.CharField(choices=[('system', 'System'), ('product', 'Product Updates'), ('security', 'Security'), ('alert', 'Alerts'), ('service', 'Service')], default='system', max_length=20, verbose_name='category')),
25+
('title', models.CharField(max_length=255, verbose_name='title')),
26+
('content', models.TextField(verbose_name='content')),
27+
('full_content', models.TextField(blank=True, verbose_name='full content')),
28+
('severity', models.CharField(choices=[('info', 'Info'), ('warning', 'Warning'), ('error', 'Error'), ('success', 'Success')], default='info', max_length=20, verbose_name='severity')),
29+
('is_read', models.BooleanField(default=False, verbose_name='is read')),
30+
('action_link', models.CharField(blank=True, max_length=500, verbose_name='action link')),
31+
('action_text', models.CharField(blank=True, max_length=255, verbose_name='action text')),
32+
('created_at', models.DateTimeField(auto_now_add=True, verbose_name='created at')),
33+
('updated_at', models.DateTimeField(auto_now=True, verbose_name='updated at')),
34+
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='messages', to=settings.AUTH_USER_MODEL, verbose_name='user')),
35+
],
36+
options={
37+
'verbose_name': 'message',
38+
'verbose_name_plural': 'messages',
39+
'ordering': ['-created_at'],
40+
},
41+
),
42+
migrations.CreateModel(
43+
name='MessagePreference',
44+
fields=[
45+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
46+
('email_alerts', models.BooleanField(default=True, verbose_name='email alerts')),
47+
('push_alerts', models.BooleanField(default=False, verbose_name='push alerts')),
48+
('webhook_url', models.URLField(blank=True, max_length=500, verbose_name='webhook url')),
49+
('notify_security', models.BooleanField(default=True, verbose_name='notify security')),
50+
('notify_system', models.BooleanField(default=True, verbose_name='notify system')),
51+
('notify_product', models.BooleanField(default=False, verbose_name='notify product')),
52+
('notify_alert', models.BooleanField(default=True, verbose_name='notify alert')),
53+
('notify_service', models.BooleanField(default=True, verbose_name='notify service')),
54+
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='message_preference', to=settings.AUTH_USER_MODEL, verbose_name='user')),
55+
],
56+
options={
57+
'verbose_name': 'message preference',
58+
'verbose_name_plural': 'message preferences',
59+
},
60+
),
61+
]

0 commit comments

Comments
 (0)