Skip to content

Commit

Permalink
Merge pull request #13 from Bioprotocols/development
Browse files Browse the repository at this point in the history
Alpha Release Candidate
  • Loading branch information
danbryce authored Feb 9, 2022
2 parents edb4263 + 15c2af7 commit c6e98c7
Show file tree
Hide file tree
Showing 90 changed files with 44,057 additions and 1,030 deletions.
55 changes: 48 additions & 7 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,14 +1,55 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST__pycache__/
*.py[cod]
*$py.class

# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal

# Flask stuff:
instance/
.webassets-cache

**/__pycache__/**
pamled/media/**/
pamled/pamled_editor/static/**
pamled/pamled_editor/templates/**
pamled/editor/static/**
pamled/editor/templates/**
**/.vscode
pamled/db.sqlite3
pamled/pamled_editor/client/.editorconfig
pamled/.env
**/node_modules
**/package-lock.json
**/.editorconfig
pamled/general.log
general.log
pamled/pamled_editor/migrations
backend/pamled_editor/migrations
backend/api/migrations
backend/editor/migrations
backend/accounts/migrations
backend/media/
oso
28 changes: 28 additions & 0 deletions Pipfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"

[dev-packages]
pylint = "*"

[packages]
Django = "==3.2.9"
django-cors-headers = "*"
djangorestframework = "*"
django-oso = "*"
jsonfield = "*"
python-decouple = "*"
pypaml = {git = "https://github.com/Bioprotocols/paml.git"}

# Keep black at version under 22 because:
# There are incompatible versions in the resolved dependencies:
# - click<8,>=7.0 (from transcriptic==9.5.0)
# - click>=8.0.0 (from black==22.1.0)
black = "<22"

[requires]
python_version = "3.9"

[pipenv]
allow_prereleases = true
1,413 changes: 1,413 additions & 0 deletions Pipfile.lock

Large diffs are not rendered by default.

145 changes: 116 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,37 +1,124 @@
# Instructions for running the PAML Editor in Development
- Install [node.js](https://nodejs.org/en/download/)
- Clone this repository (`/` is the root of the cloned repository, below)
- Set the secret key in `/pamled/.env`:
# **Introduction**

The PAML Editor (PAMLED) is a web application that supports the authoring and sharing of PAML protocols. PAMLED consists of two components: `frontend` and `backend`. The frontend is a React-based server for handling the graphical interface. The backend is a Django REST server that handles persistent storage (protocols, user accounts, and primitives), and access to the pyPAML library.

# **User Guide**

See the user guide at: [User Guide](frontend/web/src/USERGUIDE.md)

# **Running the PAML Editor in Development**

## **Pre-requisites**
- Backend <a name="backend-deps"></a>
- [Python 3.9](https://www.python.org/downloads/release/python-390/)
- [Pipenv](https://pipenv.pypa.io/en/latest/install/)
- Frontend <a name="frontend-deps"></a>
- [Node & Npm](https://nodejs.org/en/download/)


## **Backend Instructions**
---

1. On your development system install [backend dependencies](#backend-deps)

2. Get PAMLED:
```bash
git clone https://github.com/Bioprotocols/pamled.git
```
# in /
python -c "import secrets; print(f'SECRET_KEY=\"{secrets.token_urlsafe()}\"')" > pamled/.env

3. Initialize the pamled pipenv environment:
```bash
cd pamled
pipenv install
pipenv shell
```
- Create a python environment:

4. Set the secret key in `backend/.env`:
```bash
python -c "import secrets; print(f'SECRET_KEY=\"{secrets.token_urlsafe()}\"')" > backend/.env
```

5. Initialize the backend
```bash
# from within the pipenv shell
cd backend
python manage.py makemigrations accounts editor
python manage.py migrate

# optionally create a admin user
python manage.py createsuperuser
```
virutalenv env
source /env/bin/activate
pip install -r requirements.txt
```
- Install the client dependencies
```
# in /pamled/pamled_editor/client
npm install
```
- Generate the client Vue templates and copy into the Django server static files

6. Start the backend
```bash
# from within the pipenv shell, in backend/
python manage.py runserver
```
cd /pamled/pamled_editor/client
npm run build -- --mode staging

The backend server should now be running. You will see some output in the terminal like this:
```
- Optionally run the front end Vue server with the Vue CLI
Performing system checks...
System check identified no issues (0 silenced).
January 24, 2022 - 18:52:36
Django version 3.2.9, using settings 'pamled.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
```
# in /pamled/pamled_editor/client
npm run serve

## **Frontend Instructions**
---

1. On your development system install:
- [node & npm](https://nodejs.org/en/download/)

2. Initialize the frontend
```bash
# while in backend/ from above
cd ../frontend/web
npm install
```
- Run the Django server

3. Start the frontend
```bash
# while in frontend/web/
npm run start
```
# in /pamled
pip install django
python manage.py makemigrations # If you modify any of the django models
python manage.py migrate # setup the database
python manage.py runserver
```

If npm does not open a browser automatically then you can connect to the frontend at `http://localhost:3000` from your preferred browser.

4. Once connected you should be greeted by a login page. If you made a superuser account then you can login with that. Otherwise you can navigate to the sign up page and register a new account with your development database.

5. Once logged in you will see the editor.


## **Development using Visual Studio Code**
---
For those familiar with VSCode the backand and frontend instructions have mostly been encapsulated within a VSCode workspace. See the `pamled.code-workspace` in the root of the repo.

**Note** that this workspace does still require `pipenv` and `npm` to be installed.

## **Tasks**

The workspace provides a set of tasks available via command palette (`Ctrl+Shift+P`) under `Tasks: Run Task`.

These make initialization of the backend and frontend a bit easier to manage.
> ### Tasks:
> - Make Migrations
> - Migrate
> - Create Superuser
> - Nuke DB & Migrations
## **Launchers**

It also provides a set of launch commands available from the `Run and Debug` panel (`Ctrl+Shift+D`).

These make it easier to launch all of the editor parts at once.
>### Launchers
>- Django
>- React
>- Firefox
>- Chrome
>### Compound Launchers
>- Django & React & Firefox
>- Django & React & Chrome
2 changes: 2 additions & 0 deletions backend/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.env
db.sqlite3
File renamed without changes.
File renamed without changes.
26 changes: 26 additions & 0 deletions backend/accounts/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin as DjangoUserAdmin
from django.utils.translation import gettext_lazy as _

from .models import User

@admin.register(User)
class UserAdmin(DjangoUserAdmin):
"""Define admin model for custom User model with no email field."""

fieldsets = (
(None, {'fields': ('email', 'password')}),
(_('Personal info'), {'fields': ('first_name', 'last_name')}),
(_('Permissions'), {'fields': ('is_active', 'is_staff', 'is_superuser',
'groups', 'user_permissions')}),
(_('Important dates'), {'fields': ('last_login', 'date_joined')}),
)
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('email', 'password1', 'password2'),
}),
)
list_display = ('email', 'first_name', 'last_name', 'is_staff')
search_fields = ('email', 'first_name', 'last_name')
ordering = ('email',)
4 changes: 2 additions & 2 deletions pamled/pamled_editor/apps.py → backend/accounts/apps.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from django.apps import AppConfig


class PamledEditorConfig(AppConfig):
class AccountsConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'pamled_editor'
name = 'accounts'
47 changes: 47 additions & 0 deletions backend/accounts/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
from django.db import models
from django.contrib.auth.models import AbstractUser, BaseUserManager
from django.utils.translation import gettext_lazy as _

class UserManager(BaseUserManager):
"""Define a model manager for User model with no username field."""

use_in_migrations = True

def _create_user(self, email, password, **extra_fields):
"""Create and save a User with the given email and password."""
if not email:
raise ValueError('The given email must be set')
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user

def create_user(self, email, password=None, **extra_fields):
"""Create and save a regular User with the given email and password."""
extra_fields.setdefault('is_staff', False)
extra_fields.setdefault('is_superuser', False)
return self._create_user(email, password, **extra_fields)

def create_superuser(self, email, password, **extra_fields):
"""Create and save a SuperUser with the given email and password."""
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)

if extra_fields.get('is_staff') is not True:
raise ValueError('Superuser must have is_staff=True.')
if extra_fields.get('is_superuser') is not True:
raise ValueError('Superuser must have is_superuser=True.')

return self._create_user(email, password, **extra_fields)

class User(AbstractUser):
"""User model."""

username = None
email = models.EmailField(_('email address'), unique=True)

USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []

objects = UserManager()
11 changes: 11 additions & 0 deletions backend/accounts/policy/authorization.polar
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
allow(user: accounts::User, _action, _resource) if
user.is_staff;

allow(user: accounts::User, "GET", resource) if
user_owns_protocol(user, resource);

allow(user: accounts::User, "DELETE", resource) if
user_owns_protocol(user, resource);

user_owns_protocol(user: accounts::User, resource: editor::Protocol) if
resource in editor::Protocol.objects.filter(owner: user);
3 changes: 3 additions & 0 deletions backend/accounts/tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.test import TestCase

# Create your tests here.
12 changes: 12 additions & 0 deletions backend/accounts/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from django.urls import path

from . import views

urlpatterns = [
path('csrf/', views.get_csrf, name='api-accounts-csrf'),
path('signup/', views.signup_view, name='api-accounts-signup'),
path('login/', views.login_view, name='api-accounts-login'),
path('logout/', views.logout_view, name='api-accounts-logout'),
path('session/', views.SessionView.as_view(), name='api-accounts-session'),
path('whoami/', views.WhoAmIView.as_view(), name='api-accounts-whoami'),
]
Loading

0 comments on commit c6e98c7

Please sign in to comment.