Skip to content
Merged
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
89 changes: 81 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,83 @@
# README #
# 2%

Setup donezsi.eu

1. Install google cloud python sdk
2. `git clone https://bitbucket.org/donezsieu/donezsieu.git`
3. `pip install -r requirements.txt -t ./lib`
## Setup
1. Install Google App Engine Python SDK. [Details here aici](https://cloud.google.com/appengine/docs/standard/python/download#python_linux)
2. Clone the repo: `git clone https://github.com/code4romania/redirectioneaza`
3. Install the requirements in the `lib` folder (not globally): `pip install -r requirements.txt -t ./lib`
4. `bower install`
5. `git config user.email "andrei@donezsi.eu"`
6. `git config user.name "Andrei"`
5. To run the dev server you need to know the path to the App Engine SDK and be in the app's folder:
```sh
[path_to_sdk]/dev_appserver.py ./app.yaml --datastore_path=./datastore.db --enable_console
```
Read more about the Local Development Server [here](https://cloud.google.com/appengine/docs/standard/python/tools/using-local-server).
Locally, App Engine has an interface for the DB found [here](http://localhost:8000/datastore) (the server needs to be running).

## App structure
The entry point of the app is `main.py`. Here is where all the routes are defined.
The main folders are:
* `controllers` contains the handlers for each route
* `models` has the `ndb` Models and some helpers:
* `create_pdf` the logic for creating the pdf
* `email` a small wrapper over SendGrid
* `handlers` wrappers over `webapp2.RequestHandler`, they add some functionality. New handlers should inherit from `BaseHandler` or `AccountHandler`.
* `storage` contains `CloudStorage` which helps with uploading the PDFs to google cloud
* `static` all the static files: css, js, images
* `views` all the html file + email templates. New html pages should extend `base.html`

## Bulding new handlers
New handlers should extend `BaseHandler` from `models.handlers`. The path to the html file should be set as `template_name`. The app looks in the `views` folder for it.
To send props to the view, use the dict `self.template_values`.
On the `get` method, `self.render()` should be called at the end.

## Notes

### Deploying
To deploy the app from the command line, run:
```sh
gcloud app deploy --no-promote ./app.yaml --version [version]
```
`version` must be the new version of the app

#### Testing remotely
Google offers some generous free quota for App engine apps so you can create you own app engine app [here](http://console.cloud.google.com/appengine/) and deploy it there. You need a google account (gmail, etc.)

#### Deploying indexes
When adding new `ndb` Models with indexed properties, they will be automatically added in the local file named `index.yaml`. That file needs to be deployed every time it changes. To do that, run:
```sh
gcloud app deploy ./index.yaml
```

#### CSS
The app uses `LESS`. To compile the CSS, run:
```sh
cd ./static/
lessc css/main.less > css/main.css --clean-css="--s1 --advanced --compatibility=ie8"
```

### Deploying CRON jobs
To deploy the new cron jobs you need to uncomment the `application` in app.yaml and change it to your app's name (this is used only in this case)
```sh
[path_to_sdk]/appcfg.py update_cron ./
```
### Adding dummy NGOs
When you start if you might want to add some ngos. Go to the sdk's [Console](http://localhost:8000/console) and run:
```python
from models.models import NgoEntity

ngo = NgoEntity(
logo= "https://code4.ro/wp-content/uploads/2016/06/fb.png",
name= "Nume asociatie",
description= "O descriere",
id= "nume-asociatie", # this needs to be unique. Also used as the ngo's URL
account = "RO33BTRL3342234vvf2234234234XX",
cif = "3333223",
address = "Str. Ion Ionescu, nr 33"
)
ngo.put()
```
You can also add ngos from the admin.

### Read more
You can read more about the frameworks used by the app:
[webapp2](https://webapp2.readthedocs.io/en/latest/)
[jinja2](http://jinja.pocoo.org/docs/dev/templates/)
4 changes: 2 additions & 2 deletions appengine_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
DEV_DEPENDECIES_LOCATION = "/bower_components"
TITLE = "donezsi.eu"

SESSION_SECRET_KEY = "JgW`l2hZa*WV+z >}{T~Snq`DD1s@S#[Z7L>~.-;]t.7y2%gU)A^?ZTDyn/~kDh}RZA:/B{Vo7cI@TeA2Dll+0M#z|{,V*8`90VaV^`Cj&"
SESSION_SECRET_KEY = "JgW`l2hZa*WV+z >}{T~Snq`DD1s@S#[Z7L>~.-;]t.7y2%gU)A^?ZTDyn/~kDh}RZA:/BVo7cI@TeA2Dll+0M#z|{,V*8`90VaV^`Cj&"


# ADMIN
Expand All @@ -77,7 +77,7 @@
# for https everywhere, and on subdomains, 1 year
"Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload",
# make sure the certificate is valid
"Public-Key-Pins-Report-Only": 'pin-sha256="wuvbD/BvVfYoATqByqmg/6/XWyvmA+yeQImG75l2ous=";pin-sha256="6X0iNAQtPIjXKEVcqZBwyMcRwq1yW60549axatu3oDE=";pin-sha256="h6801m+z8v3zbgkRHpq6L29Esgfzhj89C1SyUCOQmqU=";max-age=2592000;report-uri="https://report-uri.io/report/donezsieu/reportOnly";includeSubdomains',
# "Public-Key-Pins-Report-Only": 'pin-sha256="wuvbD/BvVfYoATqByqmg/6/XWyvmA+yeQImG75l2ous=";pin-sha256="6X0iNAQtPIjXKEVcqZBwyMcRwq1yW60549axatu3oDE=";pin-sha256="h6801m+z8v3zbgkRHpq6L29Esgfzhj89C1SyUCOQmqU=";max-age=2592000;report-uri="https://report-uri.io/report/donezsieu/reportOnly";includeSubdomains',

# don't allow the site to be embeded
"X-Frame-Options": "Deny",
Expand Down
10 changes: 0 additions & 10 deletions controllers/ngo.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,6 @@
import json
import datetime

ngo = NgoEntity(
logo= "http://images.clipartpanda.com/spinner-clipart-9cz75npcE.jpeg",
name= "Nume asoc",
description= "o descriere lunga",
id= "ssda",
account = "RO33BTRL3342234vvf2234234234XX",
cif = "3333223",
address = "Str. Ion Ionescu, nr 33"
)
# ngo.put()

"""
Handlers used for ngo
Expand Down
52 changes: 28 additions & 24 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,13 @@
from webapp2_extras import routes
from webapp2 import Route as r

from controllers.site import *
from controllers.account_management import *
from controllers.my_account import *
from controllers.api import *
from controllers.admin import *
from controllers.ngo import NgoHandler, TwoPercentHandler, TwoPercent2Handler, DonationSucces

from controllers.site import NotFoundPage, InternalErrorPage

config = {
'webapp2_extras.auth': {
Expand Down Expand Up @@ -37,43 +41,43 @@
# use string in dotted notation to be lazily imported
app = webapp2.WSGIApplication([
# the public part of the app
r('/', handler="controllers.site.HomePage"),
r('/ong', handler="controllers.site.ForNgoHandler"),
r('/', handler=HomePage),
r('/ong', handler=ForNgoHandler),

# backup in case of old urls. to be removed
r('/pentru-ong-uri', handler="controllers.site.ForNgoHandler"),
r('/pentru-ong-uri', handler=ForNgoHandler),

r('/asociatii', handler="controllers.site.NgoListHandler"),
r('/asociatii', handler=NgoListHandler),

r('/termeni', handler="controllers.site.TermsHandler"),
r('/TERMENI', handler="controllers.site.TermsHandler"),
r('/politica', handler="controllers.site.PolicyHandler"),
r('/termeni', handler=TermsHandler),
r('/TERMENI', handler=TermsHandler),
r('/politica', handler=PolicyHandler),

# account management
r('/cont-nou', handler="controllers.account_management.SignupHandler"),
r('/login', handler="controllers.account_management.LoginHandler", name='login'),
r('/logout', handler="controllers.account_management.LogoutHandler", name='logout'),
r('/cont-nou', handler=SignupHandler),
r('/login', handler=LoginHandler, name='login'),
r('/logout', handler=LogoutHandler, name='logout'),

r('/forgot', handler="controllers.account_management.ForgotPasswordHandler", name='forgot'),
r('/forgot', handler=ForgotPasswordHandler, name='forgot'),

# verification url: used for signup, and reset password
r('/<type:v|p>/<user_id:\d+>-<signup_token:.+>', handler="controllers.account_management.VerificationHandler", name='verification'),
r('/password', handler="controllers.account_management.SetPasswordHandler"),
r('/<type:v|p>/<user_id:\d+>-<signup_token:.+>', handler=VerificationHandler, name='verification'),
r('/password', handler=SetPasswordHandler),

# my account
r('/contul-meu', handler="controllers.my_account.MyAccountHandler", name='contul-meu'),
r('/asociatia', handler="controllers.my_account.NgoDetailsHandler", name='asociatia'),
r('/date-cont', handler="controllers.my_account.MyAccountDetailsHandler", name='date-contul-meu'),
r('/contul-meu', handler=MyAccountHandler, name='contul-meu'),
r('/asociatia', handler=NgoDetailsHandler, name='asociatia'),
r('/date-cont', handler=MyAccountDetailsHandler, name='date-contul-meu'),

r('/api/ngo/check-url/<ngo_url>', handler="controllers.api.CheckNgoUrl", name='api-ngo-check-url'),
r('/api/ngo/upload-url', handler="controllers.api.GetUploadUrl", name='api-ngo-upload-url'),
r('/api/ngo/check-url/<ngo_url>', handler=CheckNgoUrl, name='api-ngo-check-url'),
r('/api/ngo/upload-url', handler=GetUploadUrl, name='api-ngo-upload-url'),

# ADMIN HANDLERS
r('/admin', handler="controllers.admin.AdminHandler", name='admin'),
r('/admin/conturi', handler="controllers.admin.UserAccounts", name='admin-users'),
r('/admin/campanii', handler="controllers.admin.SendCampaign", name='admin-campanii'),
r('/admin/ong-nou', handler="controllers.admin.AdminNewNgoHandler", name='admin-ong-nou'),
r('/admin/<ngo_url>', handler="controllers.admin.AdminNgoHandler", name='admin-ong'),
r('/admin', handler=AdminHandler, name='admin'),
r('/admin/conturi', handler=UserAccounts, name='admin-users'),
r('/admin/campanii', handler=SendCampaign, name='admin-campanii'),
r('/admin/ong-nou', handler=AdminNewNgoHandler, name='admin-ong-nou'),
r('/admin/<ngo_url>', handler=AdminNgoHandler, name='admin-ong'),


r('/<ngo_url>', handler=NgoHandler, name="ngo-url"),
Expand Down