Skip to content

Commit

Permalink
ADD anubis_developer role
Browse files Browse the repository at this point in the history
  • Loading branch information
wabscale committed Sep 20, 2022
1 parent 1403db6 commit 4113c62
Show file tree
Hide file tree
Showing 7 changed files with 147 additions and 45 deletions.
11 changes: 11 additions & 0 deletions api/anubis/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,17 @@
},
}

DEVELOPER_DEFAULT_IMAGE = "registry.digitalocean.com/anubis/theia-base"
DEVELOPER_DEFAULT_OPTIONS = {
"autosave": False,
"persistent_storage": True,
"network_policy": "os-student",
"resources": {
"requests": {"cpu": "1000m", "memory": "1Gi"},
"limits": {"cpu": "2000m", "memory": "2Gi"},
},
}

WEBTOP_DEFAULT_OPTIONS = {
"autosave": True,
"persistent_storage": False,
Expand Down
1 change: 1 addition & 0 deletions api/anubis/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ class User(db.Model):
github_username = Column(Text(length=2 ** 14), index=True)
name = Column(Text(length=2 ** 14))
is_superuser: bool = Column(Boolean, nullable=False, default=False)
is_anubis_developer: bool = Column(Boolean, nullable=False, default=False)
disabled: bool = Column(Boolean, nullable=False, default=False)
deadline_email_enabled: bool = Column(Boolean, nullable=False, default=True)
release_email_enabled: bool = Column(Boolean, nullable=False, default=True)
Expand Down
39 changes: 0 additions & 39 deletions api/anubis/views/admin/students.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,42 +197,3 @@ def admin_students_update_id(id: str, name: str = None, github_username: str = N

# Pass back the status
return success_response({"status": "saved"})


@students_.route("/toggle-superuser/<string:id>")
@require_superuser()
@json_response
def admin_students_toggle_superuser(id: str):
"""
Toggle the superuser status for a user. Requires user to be superuser
to be able to make this change.
:param id:
:return:
"""

# Get the other user
other = User.query.filter(User.id == id).first()

# Double check that the current user is a superuser
req_assert(current_user.is_superuser, message="only superusers can create superusers")

# If the other user was not found, then stop
req_assert(other is not None, message="user does not exist")

# Make sure that the other user is not also the current user
req_assert(current_user.id != other.id, message="cannot toggle your own superuser")

# Toggle the superuser field
other.is_superuser = not other.is_superuser

# Commit the change
db.session.commit()

# Pass back the status based on if the other is now a superuser
if other.is_superuser:
return success_response({"status": f"{other.name} is now a superuser", "variant": "warning"})

# Pass back the status based on if the other user is now no longer a superuser
else:
return success_response({"status": f"{other.name} is no longer a superuser", "variant": "success"})
20 changes: 17 additions & 3 deletions api/anubis/views/public/playgrounds.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from anubis.utils.auth.user import current_user
from anubis.utils.http import success_response, req_assert
from anubis.utils.http.decorators import json_response, load_from_id
from anubis.constants import DEVELOPER_DEFAULT_IMAGE, DEVELOPER_DEFAULT_OPTIONS

playgrounds_ = Blueprint("public-playgrounds", __name__, url_prefix="/public/playgrounds")

Expand Down Expand Up @@ -54,6 +55,19 @@ def public_playgrounds_initialize(theia_image: TheiaImage):
# to start a new ide.
assert_theia_sessions_enabled()

# Default status
status = "Session created"

# Default to not setting
resources = dict()
docker = False

# If the person launching is a developer, then add the extra stuff
if current_user.is_anubis_developer and theia_image.image == DEVELOPER_DEFAULT_IMAGE:
status = "Developer session created"
resources = DEVELOPER_DEFAULT_OPTIONS['resources']
docker = True

# Create IDE
session: TheiaSession = initialize_ide(
image_id=theia_image.id,
Expand All @@ -66,18 +80,18 @@ def public_playgrounds_initialize(theia_image: TheiaImage):
network_policy="os-student",
persistent_storage=True,
autosave=False,
resources=dict(),
resources=resources,
admin=False,
credentials=False,
docker=False,
docker=docker,
)

# Redirect to proxy
return success_response(
{
"active": session.active,
"session": session.data,
"status": "Session created",
"status": status,
}
)

Expand Down
68 changes: 68 additions & 0 deletions api/anubis/views/super/students.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from flask import Blueprint

from anubis.lms.students import get_students
from anubis.models import User, db
from anubis.utils.auth.http import require_superuser
from anubis.utils.data import req_assert
from anubis.utils.http import success_response
from anubis.utils.http.decorators import json_response

Expand All @@ -23,3 +25,69 @@ def super_students_list():

# Pass back the students
return success_response({"students": students})


@students_.route("/toggle-superuser/<string:id>")
@require_superuser()
@json_response
def super_students_toggle_superuser(id: str):
"""
Toggle the superuser status for a user. Requires user to be superuser
to be able to make this change.
:param id:
:return:
"""

# Get the other user
other = User.query.filter(User.id == id).first()

# If the other user was not found, then stop
req_assert(other is not None, message="user does not exist")

# Toggle the superuser field
other.is_superuser = not other.is_superuser

# Commit the change
db.session.commit()

# Pass back the status based on if the other is now a superuser
if other.is_superuser:
return success_response({"status": f"{other.name} is now a superuser", "variant": "warning"})

# Pass back the status based on if the other user is now no longer a superuser
else:
return success_response({"status": f"{other.name} is no longer a superuser", "variant": "success"})


@students_.route("/toggle-anubis_developer/<string:id>")
@require_superuser()
@json_response
def super_students_toggle_anubis_developer(id: str):
"""
Toggle the superuser status for a user. Requires user to be superuser
to be able to make this change.
:param id:
:return:
"""

# Get the other user
other: User = User.query.filter(User.id == id).first()

# If the other user was not found, then stop
req_assert(other is not None, message="user does not exist")

# Toggle the superuser field
other.is_anubis_developer = not other.is_anubis_developer

# Commit the change
db.session.commit()

# Pass back the status based on if the other is now a superuser
if other.is_anubis_developer:
return success_response({"status": f"{other.name} is now an anubis developer", "variant": "warning"})

# Pass back the status based on if the other user is now no longer a superuser
else:
return success_response({"status": f"{other.name} is no longer an anubis developer", "variant": "success"})
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
"""ADD anubis developer to user
Revision ID: 5396e908cf7b
Revises: 5ea160112b7e
Create Date: 2022-09-19 21:55:28.169282
"""
from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision = "5396e908cf7b"
down_revision = "5ea160112b7e"
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column(
"user", sa.Column("is_anubis_developer", sa.Boolean(), nullable=False)
)
# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column("user", "is_anubis_developer")
# ### end Alembic commands ###
23 changes: 20 additions & 3 deletions web/src/pages/core/super/Users.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,13 @@ const useStyles = makeStyles((theme) => ({
}));


const toggleSuperuser = (id, {setStudents, setEdits}, enqueueSnackbar) => () => {
axios.get(`/api/admin/students/toggle-superuser/${id}`).then((response) => {
const toggleField = (field) => (id, {setStudents, setEdits}, enqueueSnackbar) => () => {
axios.get(`/api/super/students/toggle-${field}/${id}`).then((response) => {
if (standardStatusHandler(response, enqueueSnackbar)) {
setStudents((students) => {
for (const student of students) {
if (student.id === id) {
student.is_superuser = !student.is_superuser;
student['is_' + field] = !student['is_' + field];
}
}
return students;
Expand All @@ -57,6 +57,9 @@ const toggleSuperuser = (id, {setStudents, setEdits}, enqueueSnackbar) => () =>
}).catch(standardErrorHandler(enqueueSnackbar));
};

const toggleSuperuser = toggleField('superuser');
const toggleDeveloper = toggleField('anubis_developer');

const useColumns = (pageState, enqueueSnackbar) => () => ([
{
field: 'id',
Expand Down Expand Up @@ -100,6 +103,20 @@ const useColumns = (pageState, enqueueSnackbar) => () => ([
</Tooltip>
),
},
{
field: 'is_anubis_developer',
headerName: 'Developer',
renderCell: (params) => (
<React.Fragment>
<Switch
checked={params.row.is_anubis_developer}
color={'primary'}
onClick={toggleDeveloper(params.row.id, pageState, enqueueSnackbar)}
/>
</React.Fragment>
),
width: 150,
},
{
field: 'is_superuser',
headerName: 'Superuser',
Expand Down

0 comments on commit 4113c62

Please sign in to comment.