Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions apps/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,17 @@ class Meta:
'apps/img/app_icon_generic.png')


APP_TYPE_DESKTOP = 'desktop'
APP_TYPE_WEB = 'web'
APP_TYPE_SERVICE = 'service'

APP_TYPE_CHOICES = [
(APP_TYPE_DESKTOP, 'Desktop'),
(APP_TYPE_WEB, 'Web'),
(APP_TYPE_SERVICE, 'Service'),
]


def app_icon_path(app, filename):
"""
Callable function used by :py:class:`~App` constructor
Expand Down Expand Up @@ -124,6 +135,13 @@ class App(models.Model):

active = models.BooleanField(default=False)

app_type = models.CharField(
max_length=10,
choices=APP_TYPE_CHOICES,
default=APP_TYPE_DESKTOP,
db_index=True,
)

def is_editor(self, user):
"""
Denotes if 'user' passed in can edit this App
Expand Down
66 changes: 64 additions & 2 deletions apps/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@
from PIL import Image, ImageDraw

from django.conf import settings
from django.core.exceptions import ValidationError
from django.core.files.uploadedfile import SimpleUploadedFile
from django.contrib.auth.models import User
from django.test import TestCase
from apps.models import App
from apps.models import App, APP_TYPE_DESKTOP, APP_TYPE_WEB, APP_TYPE_SERVICE
from apps.models import Author
from apps.models import OrderedAuthor
from apps.models import Screenshot
Expand Down Expand Up @@ -676,4 +677,65 @@ def test_app_button_by_name_found_app(self):
active=True)
appobj.save()
res = app_buttons.app_button_by_name('myapp')
self.assertEqual('myapp', res['app'].name)
self.assertEqual('myapp', res['app'].name)


class AppTypeTestCase(TestCase):

def setUp(self):
App.objects.all().delete()

def tearDown(self):
App.objects.all().delete()

def test_default_app_type_is_desktop(self):
appobj = App.objects.create(name='myapp', fullname='MyApp')
self.assertEqual(APP_TYPE_DESKTOP, appobj.app_type)

def test_app_type_persists_as_web(self):
App.objects.create(name='myapp', fullname='MyApp',
app_type=APP_TYPE_WEB)
appobj = App.objects.get(name='myapp')
self.assertEqual(APP_TYPE_WEB, appobj.app_type)

def test_app_type_persists_as_service(self):
App.objects.create(name='myapp', fullname='MyApp',
app_type=APP_TYPE_SERVICE)
appobj = App.objects.get(name='myapp')
self.assertEqual(APP_TYPE_SERVICE, appobj.app_type)

def test_invalid_app_type_fails_validation(self):
appobj = App.objects.create(name='myapp', fullname='MyApp',
app_type='invalid')
with self.assertRaises(ValidationError):
appobj.full_clean()

def test_filter_by_app_type_desktop(self):
App.objects.create(name='desktop1', fullname='Desktop One',
app_type=APP_TYPE_DESKTOP)
App.objects.create(name='web1', fullname='Web One',
app_type=APP_TYPE_WEB)
App.objects.create(name='service1', fullname='Service One',
app_type=APP_TYPE_SERVICE)
results = App.objects.filter(app_type=APP_TYPE_DESKTOP)
self.assertEqual(1, results.count())
self.assertEqual('desktop1', results.first().name)

def test_filter_by_app_type_web(self):
App.objects.create(name='web1', fullname='Web One',
app_type=APP_TYPE_WEB)
App.objects.create(name='web2', fullname='Web Two',
app_type=APP_TYPE_WEB)
App.objects.create(name='desktop1', fullname='Desktop One',
app_type=APP_TYPE_DESKTOP)
results = App.objects.filter(app_type=APP_TYPE_WEB)
self.assertEqual(2, results.count())

def test_filter_by_app_type_service(self):
App.objects.create(name='service1', fullname='Service One',
app_type=APP_TYPE_SERVICE)
App.objects.create(name='desktop1', fullname='Desktop One',
app_type=APP_TYPE_DESKTOP)
results = App.objects.filter(app_type=APP_TYPE_SERVICE)
self.assertEqual(1, results.count())
self.assertEqual('service1', results.first().name)
44 changes: 44 additions & 0 deletions dbmigration/add_app_type.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Adds app_type column to apps_app table.
#
# app_type replaces the insufficient is_service boolean and supports three
# platform states: 'desktop' (default), 'web', and 'service'.
#
# Existing rows are defaulted to 'desktop' to preserve backward compatibility.
#
# Usage:
# python add_app_type.py
#
# Make sure to update the connection credentials below before running.

import MySQLdb as mdb

DB_HOST = 'localhost'
DB_USER = 'root'
DB_PASS = ''
DB_NAME = 'CyAppStore'

con = None
try:
con = mdb.connect(DB_HOST, DB_USER, DB_PASS, DB_NAME)
cur = con.cursor()

cur.execute("""
ALTER TABLE apps_app
ADD COLUMN app_type VARCHAR(10) NOT NULL DEFAULT 'desktop'
AFTER active
""")

cur.execute("""
ALTER TABLE apps_app
ADD INDEX apps_app_app_type_idx (app_type)
""")

con.commit()
print("Migration successful: app_type column added to apps_app.")
except mdb.Error as e:
print(f"Migration failed: {e}")
if con:
con.rollback()
finally:
if con:
con.close()