Yadawia¶
Introduction¶
Built for CCIT’s E-Business Fundementals course (IS371). Its idea is simple: customer-to-customer buying and selling of goods and services, if and only if those goods and services in question are handmade.
This documentation focuses on the technical side of things rather than the business side.
Quick summary of what people should be able to do with this platform:
- Create, edit, and deactivate accounts.
- Sell handmade products.
- Buy handmade products.
- Communicate special requests to sellers.
- Search for products by their attributes.
The difference between this and a regular e-commerce platform to the user is the flexibility in making and receiving orders regarding schedules, requests, etc.
Tools¶
This project uses:
- Flask (Python) for the back-end.
- AWS S3 for image uploads.
- PostgreSQL for the database.
Installation¶
1. Clone the github repo.
$ git clone https://github.com/blaringsilence/yadawia.git
$ cd yadawia
2. Install virtualenv and activate it.
$ pip install virtualenv
$ virtualenv -p python3 venv
$ . venv/bin/activate
3. Install requirements.
$ pip install -r requirements.txt
4. Install PostgreSQL (see download page) and create a user and a database.
$ sudo -u postgres createuser -s $USER -P
$ createdb -U $USER snowdonia
5. Set environment variables (if running locally, add them to your venv/bin/activate script as follows):
export DATABASE_URL="postgresql+psycopg2://USER:PASSWORD@localhost/yadawia"
export AWS_ACCESS_KEY_ID="YOUR/YOUR IAM USER'S AWS ACCESS KEY"
export AWS_SECRET_ACCESS_KEY="YOUR/YOUR IAM USER'S SECRET ACCESS KEY"
export S3_BUCKET="YOUR BUCKET NAME HERE"
6. Create the tables, then populate them with the initial values (chmod a+x FILENAME before executing if file does not have execution permissions).
$ ./create_db.py
$ ./populate_countries.py
$ ./populate_currencies.py
$ ./populate_reasons.py
$ ./populate_categories.py
$ ./populate_methods.py
7. Run the app.
$ gunicorn yadawia:app
Docs¶
App¶
Initialize configuration for the whole app and put all the parts together.
-
yadawia.
app
= <Flask 'yadawia'>¶ Initialize app.
-
yadawia.
csrf_protect
()[source]¶ Check for csrf token in POST and DELETE requests. CSRF tokens are generated per session/login. If there’s no token or the token is not equal to the one from the form, abort the request.
-
yadawia.
css_libs
= <Bundle output=css/all.css, filters=[<webassets.filter.cssmin.CSSMin object>], contents=('css/layout.css', 'css/jquery-ui.structure.min.css', 'css/font-awesome.min.css', 'css/bootstrap.min.css', 'css/jquery-ui.min.css')>¶ Bundle library css files and minify them.
-
yadawia.
db
¶ Use SQLAlchemy as an ORM.
-
yadawia.
excerpt
(text)[source]¶ TEMPLATE FILTER: Cut text and append dots if its lenght is more than 100 chars.
-
yadawia.
js
= <Bundle output=js/all.js, filters=[<webassets.filter.slimit.Slimit object>], contents=('js/form_edit_profile.js', 'js/form_login.js', 'js/form_review.js', 'js/cart.js', 'js/order_history.js', 'js/form_change_pic.js', 'js/analytics.js', 'js/moment.js', 'js/checkout.js', 'js/jquery-ui.min.js', 'js/functions.js', 'js/index.js', 'js/profile_products.js', 'js/create_product.js', 'js/form_register.js', 'js/form_settings.js', 'js/bootstrap.min.js', 'js/review_card.js', 'js/product.js')>¶ Bundle all JavaScript files and minify them.
-
yadawia.
jsglue
= <flask_jsglue.JSGlue object>¶ Initialize Flask-JSGlue which allows us to use Flask.url_for in un-rendered JavaScript.
Views¶
Contains all the view logic/endpoints for this app.
-
yadawia.views.
cart_products
()[source]¶ AJAX endpoint for cart pages: get info about products in cart.
-
yadawia.views.
deactivate_account
()[source]¶ Deactivate a user’s account. Can be undone by simply logging in again, as opposed to admin suspension (yet to be implemented in a view).
-
yadawia.views.
edit_product
(productID)[source]¶ Edit product (edit non-image attributes and add new images).
-
yadawia.views.
new_message
()[source]¶ Send a new message (start a new message thread) with another user.
-
yadawia.views.
order_history
()[source]¶ Get someone’s order history. Orders by them, and orders for them.
-
yadawia.views.
profile
(username=None)[source]¶ View function for profile given a username OR if not, use username of logged in user. Returns:
- user: Object instance of type User.
- is_curr_user: Boolean = is this the logged in user’s profile?
- avg_rating: user’s average rating throughout their products.
- products: user’s products (all if is_curr_user, available only if not).
- report_reasons: reasons to report a user if not is_curr_user.
Classes¶
Contains all the classes (database, exceptions, etc) created for this app.
-
class
yadawia.classes.
Address
(name, user_id, text, country_id, code=None, phone=None)[source]¶ Database model for addresses (physical). Contains:
- id: int, auto-incremented.
- name: name to assign to this address (every user can have multiple addresses).
- user_id: int, foreign key.
- country_id: string, ISO 3166-1 code, foreign key.
- city: string.
- zip/postal code: string.
- phone: string.
- text: string.
-
class
yadawia.classes.
Admins
(user_id)[source]¶ Database model for admins. Contains:
- id: int, auto-incremented.
- user_id: int, foreign key.
- date: date.
-
class
yadawia.classes.
Category
(name)[source]¶ Database model for categories. Contains:
- id: int, auto-incremented.
- name: string.
-
class
yadawia.classes.
Country
(country_id, value)[source]¶ Database model for all countries. Contains: - id: string, ISO 3166-1 code. - value: string, name.
-
class
yadawia.classes.
Currency
(curr_id, name, symbol=None)[source]¶ Database model for all supported currencies. Contains:
- id: string, ISO-4217 code.
- name: string.
- symbol: string.
-
exception
yadawia.classes.
DBException
[source]¶ Custom exceptions raised on the ORM level. In its 0th arg, has a human-readable message and a code.
-
class
yadawia.classes.
Featured
(product_id, notes=None)[source]¶ Database model for featured products. Contains:
- id: int, auto-incremented, primary key.
- product_id: id for the featured product.
- date: date it was featured.
- notes: editor/admin’s notes on why they featured it.
-
exception
yadawia.classes.
LoginException
[source]¶ Custom exceptions raised on when logging in. In its 0th arg, has a human-readable message and a code.
-
class
yadawia.classes.
Message
(thread_id, sender_id, text)[source]¶ Database model for messages in a thread. Contains:
- id: int, auto-incremented.
- thread_id: int, foreign key.
- sender_id: int, foreign key. No need for receiver because thread has info.
- date: date.
- text: string.
- seen: date.
-
class
yadawia.classes.
MessageThread
(user1, user2, title=None)[source]¶ Database model for message threads. Contains:
- id: int, auto-incremented.
- user1: int, foreign key.
- user2: int, foreign key.
- title: string. Optional.
- order_id: int, foreign key (if about an order).
-
class
yadawia.classes.
Order
(user_id, address_id=None, payment_method_id=None)[source]¶ Database model for orders. Contains:
- id: int, auto-increment.
- user_id: int, foreign key.
- create_date: date.
- update_date: date.
- status: string. (New, Ongoing, All confirmed, On its way, Done)
- address_id: int, foreign key.
- payment_method_id: int, foreign key.
-
class
yadawia.classes.
OrderProduct
(order_id, product_id, price, currency_id, variety_id=None, quantity=1, remarks=None)[source]¶ Database model for relationship between orders and models (many-to-many). Contains:
- id: int, auto-incremented.
- order_id: int, foreign key.
- product_id: int, foreign key.
- variety_id: int, foreign key.
- quantity: int.
- create_date: date.
- update_date: date.
- remarks: string.
- price: price at time of checkout.
- currency_id: currencyID at time of checkout.
- confirmed: boolean: is this item confirmed by the seller?
-
class
yadawia.classes.
PaymentMethod
(name, fee=0, isPercentFee=False, currency_id=None)[source]¶ Database model for payment methods. Contains:
- id: int, auto-incremented.
- name: string (Cash on delivery, etc).
- fee: float (extra fee taken to use this method).
- isPercentFee: Boolean (is the fee a percentage? true = yes, false = fee is flat)
- currency_id: currency for fee if it’s flat
-
class
yadawia.classes.
Product
(name, seller_id, description=None, price=None, currency_id=None)[source]¶ Database model for products. Contains:
- id: int, auto-incremented.
- name: string.
- seller_id: int, foreign key.
- update_date: date.
- create_date: date.
- description: string.
- price: float.
- available: boolean, default: True.
-
class
yadawia.classes.
ProductCategory
(product_id, category_id)[source]¶ Database model for the relationship between products and categories (many-to-many). Contains:
- product_id: int, foreign key.
- category_id: int, foreign key.
-
class
yadawia.classes.
Reason
(text)[source]¶ Database model for report reasons. Contains:
- id: int, auto-incremented.
- text: string.
-
class
yadawia.classes.
Report
(sender_id, about_id, reason_id, message)[source]¶ Database model for reports to admins. Contains:
- id: int, auto-incremented.
- sender_id: int, foreign key.
- about_id: int, foreign key.
- reason: int, foreign key.
- date: date.
-
class
yadawia.classes.
Review
(user_id, product_id, rating, title=None, text=None)[source]¶ Database model for reviews on products. Contains:
- id: int, auto-increment.
- user_id: int, foreign key.
- product_id: int, foreign key.
- rating: float.
- title: string.
- text: string.
- create_date: review date.
- update_date: update date.
-
class
yadawia.classes.
Upload
(filename, product_id, variety_id=None, order=0)[source]¶ Database model for product-related uploads (photo, video). Contains:
- id: int, auto-increment.
- filename: string.
- date: upload date.
- product_id: int, foreign key.
- variety_id: int, foreign key. Optional.
- order: int, default: 0
-
class
yadawia.classes.
User
(username, email, password, name=None, location=None)[source]¶ Database model for users. Contains:
- id: int, auto-incremented.
- username: string.
- name: string. Optional.
- email: string.
- password: string.
-
validate_email
(key, em)[source]¶ Validate that the email has an @ and characters before and after it. Raises a DBException if invalid.
-
validate_location
(key, loc)[source]¶ Validate that the location contains anything but special characters. Raises a DBException if invalid.
-
validate_name
(key, name_input)[source]¶ Validate that the name contains anything but numbers and special characters. Raises a DBException if invalid.
-
class
yadawia.classes.
Variety
(name, product_id, price=None, available=True)[source]¶ Database model for varieties in products (sizes, etc). Contains:
- id: int, auto-incremented.
- product_id: int, foreign key.
- name: string. What is this variety? (e.g. Size small) No validation.
- price: float.
- available: boolean, default: True.
Helpers¶
Contains helper functions (decorators, others) used by other parts of the app.
-
yadawia.helpers.
anonymous_only
(f)[source]¶ Decorator function to ensure user is NOT logged in before a page is visited.
-
yadawia.helpers.
assetsList
(app, folder='js', extension='js', exclusions=[])[source]¶ Get list of files of a specific extension in a folder inside the static directory.
-
yadawia.helpers.
authenticate
(f)[source]¶ Decorator function to ensure user is logged in before a page is visited.
-
yadawia.helpers.
create_edit_product
(create=True, productID=None)[source]¶ Function to create or edit a product (used in views).
-
yadawia.helpers.
curr_user
(username)[source]¶ True if this username is that of the logged in user, false otherwise.
-
yadawia.helpers.
generate_csrf_token
(force=False)[source]¶ Create a CSRF-protection token if one doesn’t already exist in the user’s session (or force it, as done per login) and put it there.
-
yadawia.helpers.
get_presigned_post
(filename, filetype)[source]¶ Use boto3 the AWS Python SDK to generate a presigned post for S3.
-
yadawia.helpers.
get_random_string
(length=32)[source]¶ Generate a random string of length 32, used in
generate_csrf_token()
-
yadawia.helpers.
is_allowed_in_thread
(threadID)[source]¶ Given a threadID, is the signed in user allowed in the thread?
-
yadawia.helpers.
login_user
(username, password)[source]¶ Function to login user through their username. Sets:
- session[‘logged_in’] to True.
- session[‘username’] to the username.
- session[‘userId’] to the user ID.
Raises LoginException (represented as e here) if:
- User with that username does not exist (e.args[0][‘code’] = ‘username’)
- Password is incorrect (e.args[0][‘code’] = ‘password’)
-
yadawia.helpers.
no_special_chars
(string, allowNumbers=False, optional=True, allowComma=False)[source]¶ Function to check if a string has no special characters.
-
yadawia.helpers.
public
(obj, keys)[source]¶ Pass a db class object and a list of keys you don’t want returned (e.g. password hash, etc) and get a filtered dict.
-
yadawia.helpers.
redirect_back
(endpoint, **values)[source]¶ Helper function to redirect to ‘next’ URL if it exists. Otherwise, redirect to an endpoint.
Error handlers¶
How to handle common HTTP errors.
-
yadawia.errorhandlers.
bad_request
(e)[source]¶ Render error template with the message: Bad Request and no details.
-
yadawia.errorhandlers.
forbidden
(e)[source]¶ Render error template with the message: Forbidden and no details.
-
yadawia.errorhandlers.
gone
(e)[source]¶ Render error template with the message: Page Gone and no details.
-
yadawia.errorhandlers.
internal_error
(e)[source]¶ Render error template with the message: Internal Server Error and no details.
-
yadawia.errorhandlers.
not_found
(e)[source]¶ Render error template with the message: Page Not Found and details.
-
yadawia.errorhandlers.
render_error
(code, msg, det='Oops..')[source]¶ Render template with variables appropriate to the error provided.
Render error template with the message: Unauthorized and details.