This app provides users, organisations and global admins an interface to manage their own (and others) user and billing details. It also provides login support for the Law Browser.
- Install composer
curl -sS https://getcomposer.org/installer | sudo php -- --install-dir=/usr/bin
- Copy
.env.example
to.env
and fill in the blanks - Create a new database called
catalex_users
- Use composer to install PHP dependencies
composer install
- Install JS dependencies
npm install
- Install gulp globally
npm install -g gulp
- Migrate the DB
php artisan migrate
- Seed the DB
php artisan db:seed --seeder=DevelopmentSeeder
./vendor/bin/phpunit
Log testing stats: --log-junit=log_name.xml
Run specific test: --filter=test_class_name_or_test_name
To perform the initial deployment on a live server, clone the https://github.com/joshgagnon/catalex_utils.git repo. Edit the variables at the top of the install_users.sh script then run it as root.
For each service that needs to authenticate with CataLex, add a client and an endpoint for that client (example below).
The --name="whatever"
is important—we match on it to find the right oauth_client record. For Good Companies the name is "Good Companies", for Law Browser the name is "Law Browser", and for sign the name is "Sign".
php artisan oauth:add-client --client_id=gc --secret=gc --name="Good Companies"
php artisan oauth:add-endpoint --client_id=gc --endpoint=http://localhost:5667/auth/catalex/login
Currently the only OAuth provider setup is LinkedIn. For LinkedIn OAuth to work, it's ket and secret need to be entered into a new file config/oauth.php
. Use config/oauth.example.php
as an example.
Live installations can be updated with the following command:
sudo ./update.sh www-data
It must be run as root and provide the webserver username to avoid file permission errors. It will pull updates from git, apply migrations and update dependencies, so the application may be in the 'down' status for a few minutes.
To add non-model specific, non-controller functionality to the app, the best place is app/Library
. Functionality that won't need to be mocked for testing should be made as a static function directly accessible on in a library class. Testable functions should not be static, even if they require no state - instead use non-static methods and add a class binding in App\Providers\AppServiceProvider
.
All emails must pass through a css inliner before being sent, so do not use the laravel provided Mail
class directly but instead use App\Library\Mail
. To create an new email, extend the emails.ink-template
view and use a table-based layout as describe by the Zurb Ink documentation.
When using the User
model, note that it has an applied scope which filters out inactive users in the same way the default SoftDelete
scope does. The scope adds a withInactive()
builder method equivalent to the Laravel withTrashed()
. They can be used together to retrieve a user who was made inactive before being deleted.
php artisan tinker
App\Service::create(['name' => 'CataLex Sign', 'is_paid_service' => true]);
Upgrade to Laravel 5.5 LTS.
Move out all authorisation logic (eg. checking if a user is a global admin) from controllers to middleware applied in the routes file.
Dead code elimination.
Consistent styling of pages.
Better, more intuitive navigation between pages. Construct Information Architecture first, so it is well thought out.
Fix footer - it looks weird.
Better documentation.
More consistent use of Laravel features, eg. Route Model Binding, using $request->user() instead of facade, etc.
Create code style and bring all code into new code style.
Clean up billing simulation tests.
Move to new Laravel OAuth.
Use the OAuth classes for service based api auth, instead of looking in the db for the secret to match.
- Add new item type to database constraint:
- Create a DB migration to add the new item type name to the billing item type constraint. See
2018_02_08_194348_add_court_costs_to_billing_item_types
. - Otherwise just drop this constraint all together.
- Use this migration to also add the service to the database, see
2018_02_13_230335_add_court_costs_serivce.php
. - Run migrations.
- Create a DB migration to add the new item type name to the billing item type constraint. See
- In
app/BillingItem.php
:- Add
const ITEM_TYPE_WHATEVER = 'item_type_whatever'
. This is what it is saved in the DB as and must add what was added in the DB constraint. - Add that to
$itemTypes
. - Add a case to the switch in the function
description()
. This is used on the invoice.
- Add
- Wire up the new stats
- Add the new billing item to
AdminController
'sstats()
function inapp/Http/Controllers/AdminController.php
. - Add the new stat item the the template
resources/views/admin/stats.blade.php
. - Alternatively, make this all more generic.
- Add the new billing item to
- Send welcome email when user subscribes:
- In
SubscriptionController
'supdate()
method, see where other services are checking if they need to send an email, and add for the new service. - You will also need to create an email template, see how other services do this in the same method.
- In
- Add pricing:
- In
config/constants.php
add monthly and yearly pricing. - In
app/Models/Billable.php
'spriceForBillingItem()
method, add a new switch case for the new billing item.
- In
- Add ability for subscription to be added as a monthly or yearly billing item payment:
- In
app/Service.php
addconst SERVICE_NAME_WHATEVER = 'Whatever'
. - In
app/User
'ssyncSubscriptionsWithBillingItems()
method, add the new service type to the$serviceTypeMappings
array.
- In
- Update the 'Edit Subscription' views (the first for organisations, the second individuals):
resources/views/subscriptions/org/edit.blade.php
resources/views/service-user/edit.blade.php
- Add to the home page
resources/views/user/home.blade.php
. - TEST IT!
- Ask me why my instructions didn't work.
Lots of this could be done way nicer with a bit of TLC:
- stats could be more generic.
- descriptions could be in a config file and have no need for a switch.
- syncSubscriptionsWithBillingItems could be in a config file rather than code.
SubscriptionController->update()
could be way way way nicer and easier to add to - could even be based on a config file.- other such improvements.