Skip to content

Commit

Permalink
Allow creation of map folders restricted to admins only. (#1175)
Browse files Browse the repository at this point in the history
* Allow creation of map folders restricted to admins only.

* Implemented downgrade in mapfolder visibility database migration.
  • Loading branch information
TheMaximum committed Sep 16, 2022
1 parent 3078458 commit 13734cc
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 17 deletions.
12 changes: 6 additions & 6 deletions pyplanet/apps/contrib/jukebox/folders.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ async def get_folders(self, player):
raw_list = await Folders.objects.execute(
Folders.select(Folders, Player)
.join(Player)
.where((Player.login == player.login) | (Folders.public == True))
.order_by(Folders.public.desc())
.where(((Player.login == player.login) & ((Folders.visibility == 'private') | (player.level >= player.LEVEL_ADMIN))) | (Folders.visibility == 'public'))
.order_by(Folders.visibility.desc())
)

# Convert to the wanted objects.
Expand All @@ -73,7 +73,7 @@ async def get_folders(self, player):
folder_list.append(
{
'id': folder_id, 'name': folder.name, 'owner_login': folder.player.login,
'owner': folder.player.nickname, 'type': 'public' if folder.public else 'private'
'owner': folder.player.nickname, 'type': folder.visibility
}
)

Expand All @@ -90,7 +90,7 @@ async def get_private_folders(self, player):
return await Folders.objects.execute(
Folders.select(Folders, Player)
.join(Player)
.where((Player.login == player.login) & (Folders.public == False))
.where((Player.login == player.login) & (Folders.visibility == 'private'))
)

async def get_writable_folders(self, player):
Expand All @@ -105,13 +105,13 @@ async def get_writable_folders(self, player):
return await Folders.objects.execute(
Folders.select(Folders, Player)
.join(Player)
.where((Player.login == player.login) | (Folders.public == True))
.where((Player.login == player.login) | (Folders.visibility == 'public' or Folders.visibility == 'admins_only'))
)

return await Folders.objects.execute(
Folders.select(Folders, Player)
.join(Player)
.where((Player.login == player.login))
.where((Player.login == player.login) & (Folders.visibility == 'private'))
)

async def create_folder(self, **kwargs):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from peewee import RawQuery, BooleanField
from playhouse.migrate import migrate, SchemaMigrator

from ..models.mapfolder import MapFolder


def upgrade(migrator: SchemaMigrator):
try:
query = RawQuery(MapFolder, """SELECT * FROM `mapfolder` WHERE public = 1""")
public_folders = query.execute()

migrate(
migrator.add_column(MapFolder._meta.db_table, 'visibility', MapFolder.visibility),
migrator.drop_column(MapFolder._meta.db_table, 'public')
)

MapFolder.update(visibility='public').where(MapFolder.id << [f.id for f in public_folders]).execute()
except Exception as e:
print(str(e))
print('Migration failed but silencing error!')

def downgrade(migrator: SchemaMigrator):
try:
query = RawQuery(MapFolder, """SELECT * FROM `mapfolder` WHERE visibility = 'public'""")
public_folders = query.execute()

migrate(
migrator.add_column(MapFolder._meta.db_table, 'public', BooleanField()),
migrator.drop_column(MapFolder._meta.db_table, 'visibility')
)

MapFolder.update(public=True).where(MapFolder.id << [f.id for f in public_folders]).execute()
except Exception as e:
print(str(e))
print('Migration failed but silencing error!')
12 changes: 9 additions & 3 deletions pyplanet/apps/contrib/jukebox/models/mapfolder.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,21 @@ class MapFolder(TimedModel):
Folder name
"""

public = BooleanField()
visibility = CharField(
max_length=50,
null=False,
default='private'
)
"""
Is folder public (only for admins)?
Visibility of the folder (public, private, admin_only).
"""

@property
def icon(self):
if self.public:
if self.visibility == 'public':
return '\uf0c0'
elif self.visibility == 'admins_only':
return '\uf0c1'
return '\uf023'


Expand Down
15 changes: 15 additions & 0 deletions pyplanet/apps/contrib/jukebox/templates/folder_create.Script.Txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ declare Entry_AdminStatus_Value <=> (Page.GetFirstChild("folder_is_admin") as CM

declare Quad_FolderPrivacy_Public_Boolean <=> (Page.GetFirstChild("folder_privacy_public") as CMlQuad);
declare Quad_FolderPrivacy_Private_Boolean <=> (Page.GetFirstChild("folder_privacy_private") as CMlQuad);
declare Quad_FolderPrivacy_AdminsOnly_Boolean <=> (Page.GetFirstChild("folder_privacy_admins_only") as CMlQuad);

while(True) {
foreach (Event in PendingEvents) {
Expand All @@ -13,15 +14,29 @@ while(True) {
if (Entry_AdminStatus_Value.Value == "1") {
// Uncheck other one.
Quad_FolderPrivacy_Private_Boolean.StyleSelected = False;
Quad_FolderPrivacy_AdminsOnly_Boolean.StyleSelected = False;
Quad_FolderPrivacy_Public_Boolean.StyleSelected = True;

Entry_FolderPrivacy_Value.Value = "public";
}
}

if (Event.Type == CMlScriptEvent::Type::MouseClick && Event.ControlId == "folder_privacy_admins_only") {
// Check Admin status
if (Entry_AdminStatus_Value.Value == "1") {
// Uncheck other one.
Quad_FolderPrivacy_Private_Boolean.StyleSelected = False;
Quad_FolderPrivacy_AdminsOnly_Boolean.StyleSelected = True;
Quad_FolderPrivacy_Public_Boolean.StyleSelected = False;

Entry_FolderPrivacy_Value.Value = "admins_only";
}
}

if (Event.Type == CMlScriptEvent::Type::MouseClick && Event.ControlId == "folder_privacy_private") {
// Uncheck other one.
Quad_FolderPrivacy_Private_Boolean.StyleSelected = True;
Quad_FolderPrivacy_AdminsOnly_Boolean.StyleSelected = False;
Quad_FolderPrivacy_Public_Boolean.StyleSelected = False;

Entry_FolderPrivacy_Value.Value = "private";
Expand Down
3 changes: 3 additions & 0 deletions pyplanet/apps/contrib/jukebox/templates/folder_create.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@

<quad pos="0 -10" id="folder_privacy_public" size="5 5" style="Icons64x64_1" substyle="Check" styleselected="0" valign="top" scriptevents="1" />
<label pos="10 -11" size="100 5" text="$fff$oPublic, readable by everyone, writable by admins. (only for admins)" textsize="1.1" valign="top" />

<quad pos="0 -15" id="folder_privacy_admins_only" size="5 5" style="Icons64x64_1" substyle="Check" styleselected="0" valign="top" scriptevents="1" />
<label pos="10 -16" size="100 5" text="$fff$oAdmins only, visible and writable for admins. (only for admins)" textsize="1.1" valign="top" />
</frame>

<label pos="30 -100" style="CardButtonMedium" valign="center" halign="center"
Expand Down
26 changes: 18 additions & 8 deletions pyplanet/apps/contrib/jukebox/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -356,8 +356,8 @@ async def get_data(self):

async def remove_from_folder(self, player, values, map_dictionary, view, **kwargs):
# Check permission on folder.
if (self.folder_instance.public and player.level < player.LEVEL_ADMIN)\
or (not self.folder_instance.public and self.folder_instance.player_id != player.id):
if (self.folder_instance.visibility != 'private' and player.level < player.LEVEL_ADMIN)\
or (self.folder_instance.visibility == 'private' and self.folder_instance.player_id != player.id):
await show_alert(player, 'You are not allowed to remove the map from the folder!', size='sm')
return

Expand All @@ -383,6 +383,7 @@ async def get_buttons(self):
buttons = await super().get_buttons()

if (self.folder_code['type'] == 'public' and self.player.level >= self.player.LEVEL_ADMIN) \
or (self.folder_code['type'] == 'admins_only' and self.player.level >= self.player.LEVEL_ADMIN) \
or (self.folder_code['type'] == 'public' and self.folder_code['owner_login'] == self.player.login) \
or (self.folder_code['type'] == 'private' and self.folder_code['owner_login'] == self.player.login):
buttons.append({
Expand Down Expand Up @@ -484,9 +485,19 @@ def render_folder_name(row, field):
icon = '\uf0c0'
elif row['type'] == 'private':
icon = '\uf023'
elif row['type'] == 'admins_only':
icon = '\uf0c1'

return '{} {}'.format(icon, row[field['index']])

@staticmethod
def render_type(row, field):
type_name = row['type'].capitalize()
if type_name == 'Admins_only':
type_name = 'Admins only'

return type_name

async def get_fields(self):
return [
{
Expand All @@ -505,8 +516,7 @@ async def get_fields(self):
'sorting': True,
'searching': False,
'width': 30,
'renderer': lambda row, field:
row[field['index']].capitalize(),
'renderer': self.render_type,
'type': 'label'
},
{
Expand Down Expand Up @@ -662,7 +672,7 @@ async def save(self, player, action, values, *args, **kwargs):
folder_name = values['folder_name']
folder_privacy = values['folder_privacy']

if folder_privacy == 'public' and player.level < player.LEVEL_ADMIN:
if folder_privacy != 'private' and player.level < player.LEVEL_ADMIN:
folder_privacy = 'private'

# Check if the user has already created 5 private folders
Expand All @@ -679,7 +689,7 @@ async def save(self, player, action, values, *args, **kwargs):
return await show_alert(player, 'The name you gave is not valid. Please provide a name with at least 3 characters.', 'sm')

# Create folder.
await self.folder_manager.create_folder(name=folder_name, player=player, public=folder_privacy == 'public')
await self.folder_manager.create_folder(name=folder_name, player=player, visibility=folder_privacy)

# Return response.
self.response_future.set_result(None)
Expand Down Expand Up @@ -752,9 +762,9 @@ async def handle_catch_all(self, player, action, values, **kwargs):
return # Ignore exceptions here, could be that the folder has been deleted recently.

# Check permission on folder.
if folder.public and player.level < player.LEVEL_ADMIN:
if folder.visibility != 'private' and player.level < player.LEVEL_ADMIN:
return
if not folder.public and folder.player_id != player.id:
if folder.visibility == 'private' and folder.player_id != player.id:
return

# Add map to folder.
Expand Down

0 comments on commit 13734cc

Please sign in to comment.