Challenge Overview

Solar Land Solutions provide contract land services for solar and wind energy projects and more. Experienced in energy development and land acquisition in 15 states and growing!

We are building a website that matches up landowners with suitable land for community and utility solar projects with solar developers who are looking to lease the land for such a development.  

Challenge Requirements

You will address the following in this challenge :

NodeJS Framework and Modules

  • - You will use MongoDB, NodeJS, ExpressJS, and AngularJS stack in this challenge.

  • - You are required to use open source node module such as async to deliver a high quality, well organized code.

Models

Proposed mongo collection scheme, you can make modification and suggest improvements :

  • - User

    • - username

    • - password (salted)

    • - email

    • - address

    • - ToU (yes/no)

    • - role (landowner, developer, admin)

    • - companyDetails (optional)

    • - documents (optional) - array of files objects

    • - suspended (true/false)

    • - suspendedBy (user reference)

    • - suspensionReason (string)

  • - Site

    • - LandOwner

      • - Name

      • - Email

      • - Phone

      • - Address

        • - Address1

        • - Address2

        • - City

        • - State

        • - Zip

      • - UtilityArea

      • - OtherOwners (Yes/No)

      • - lifeEstateInterest (Yes/Now)

    • - Status (Draft, Pending Approval, Approved, and Rejected) - default to draft

    • - Deleted (true/false) - default to false

    • - Details

      • - Address

        • - Address1

        • - Address2

        • - City

        • - State

        • - Zip

      • - TaxID

      • - ZoningInfo

      • - ParcelSize

      • - ParcelSizeUnit

      • - AvailableForDevelopment

      • - desiredLeaseRates ($$)

        • - unit

        • - min

        • - max

      • - minimalPerAcreRental (Yes/No)

    • - AdditionalDetails

      • - underAgreementForSolarProject (Yes/No)

      • - hasWetLands (Yes/No)

      • - hasStreamsPonds (Yes/No)

      • - SlopeInfo

        • - Type (Rolling/Flat)

        • - Degree (number)

        • - Direction (North/Sounth/East/West)

      • - EndangeredSpecies (yes/no)

      • - HistoricalSites (Yes/No)

      • - SuperFundIndisterialLocation (Yes/No)

      • - WoodedPercentage (number)

      • - VegetationType (String)

      • - MineralOwernship (Yes/No)

      • - EncumberancesDetails

        • - Easements (Yes/No)

        • - EasementsDetails

        • - Mortgages (yes/no)

        • - MortagesDetails

        • - OtherLeases (Yes/No)

        • - OtherLeasesDetails

        • - Other (yes/no)

        • - OtherDetails

      • - Grading (0 - 100)

      • - Files (array of files objects)

      • - OtherInfo (string)

    • - Auditing fields

  • - SiteReview

    • - SiteId

    • - Reason

    • - Site (this a clone of reviewed Site object - for history purpose)

    • - auditing fields

  • - SiteInterests

    • - SiteId

    • - UserId

    • - Details

    • - Files - array of files objects

    • - auditing fields

  • - SiteFavorites

    • - SiteId

    • - UserId

    • - auditing fields

Rest API Functionality

You will build REST API, here is list of endpoints to implement, you can suggest changes but you need to post in forums for confirmation and discussion :

  • - Auditing fields are only populated by backend.

  • - Signup

    • - route : POST /signup

    • - input parameters are :

      • - username (required)

      • - password (required)

      • - email (required)

      • - address (required)

      • - ToU (required)

      • - role (required)

      • - companyDetails (required if role is developer)

      • - documents (required if role is developer) - array of files.

    • - if terms of use is not checked return error.

    • - create new user model, password should be hashed.

    • - use gridfs to store the files, the user model will reference the files documents.

    • - response should be the created document.

  • - Login

    • - route : POST /signin

    • - input parameters :

      • - username

      • - password

    • - Validate username/password and login the user.

    • - If the authorization are valid, then use JWT to generate token, with configurable expiration date, then return generated authorization token in response.

  • - Forgot Password

    • - Route : POST /forgotpassword

    • - Input parameter is :

      • email address or username (required)

    • - The endpoint logic :

      • - validate input parameters

      • - validate the email address or username

      • - check if there is a user with email/username, if not, return error

      • - create a reset password link with token and expiration date.

      • - send reset password email to user

        • - the email template should be configurable

        • - the from email should be configurable

    • - Response should be json with ‘success’ : true value on success, or success : false with message field set for reason of failure.

  • - Reset User Password

    • - Route : POST /resetpassword

    • - Input parameters are the query string parameters constructed in Forgot Password endpoint plus the new password.

    • - Validate the reset password parameters before updating the user password, the new password should be salted and stored.

    • - response should be a ‘success’ attribute with true/false depends on the execution result, with ‘message’ attribute if it is a failure.

  • - CRUD operations for user collection

    • - Create the following endpoints to create, update, retrieve, and retrieveall user collections.

    • - All these endpoints require valid authorization header.

    • - GET /users

      • - Only admin can access this endpoint.

      • - Enforce pagination in this endpoint

      • - Filtering parameters are optional :

        • - role

        • - suspended

      • - Return array of users documents that match the passed in criteria.

    • - GET /user/{id}

      • - Any user can access this endpoint.

      • - Return user document of the provided id.

    • - POST /users

      • - Only admin can access this endpoint

      • - input parameters will be user collection :

        • - username (required)

        • - password (required)

        • - email (required)

        • - address (required)

        • - role (required)

        • - companyDetails (required if role is developer)

        • - documents (required if role is developer) - array of files.

      • - Response should be created user.

    • - PUT /user/{id}

      • - Any authorized user can access this endpoint.

      • - For non admin, the authorized user should be the same user being updated.

      • - User can update her password in this endpoint. there should be new parameter called : newPassword.

        • - The old password field should be provided if newPassword is present.

      • - For admin user, the following parameters can be passed and optional :

        • - suspended (true/false)

        • - suspendedReason (text)

        • - If suspended is passed then set suspendedBy to be the authorized admin.

      • - Input parameters are same as in POST /users but fields are optional.

      • - Response should be updated user.

  • - Sites endpoints :

    • - All endpoints require valid authorization header

    • - POST /sites

      • - landowner and admin can create sites.

      • - input parameters are :

        • - Action : draft or submit

        • - files to be uploaded

        • - Site collection fields excluding following parameters :

          • - status

          • - deleted

          • - AdditionalDetails#Files field as we upload new files in create.

          • - auditing fields

        • - Grading field can only be set by admin user.

      • - all input parameters are optional.

      • - for non admin :

        • - set status to draft if action is draft

        • - set status to ‘Pending Approval’ if action is submit

      • - use gridfs to store the passed in files, the model will reference the files documents.

      • - Response should be the created site.

    • - PUT /site/{id}

      • - accessed by landowners or admin only.

      • - input parameters are :

        • - Action : draft or submit

        • - files to be uploaded

        • - Site collection fields excluding following parameters :

          • - status

          • - deleted

          • - auditing fields

        • - Grading can only be assigned by admin user.

      • - validate site of provided id exists

      • - if deleted is true then return error

      • - If status is approved then return error.

      • - Site can be updated only if status is “Pending Approval” or “Draft”.

      • - use gridfs to store the passed in files, the model will reference the files documents.

      • - for AdditionalDetails#Files field user should be able to remove existing file or add new files.

      • - any field (except id and status) in the site can be updated.

      • - Response should be the updated site.

    • - GET /sites

      • - can be accessed by any user

      • - should enforce pagination

      • - Input parameters :

        • - Filtering parameters

          • - site Id

          • - State

          • - Country

          • - Utility Area

          • - Address

          • - Grading

            • - min

            • - max

          • - PropertySize (you need to make proper conversion between units)

            • - unit

            • - min

            • - max

          • - EstimatedCost (you need to make proper conversion between units)

            • - Unit ($/MW DC or $/acre/year)

            • - min

            • - max

        • - status : draft, rejected, approved, pending approval

        • - deleted : true/false

        • - pagination

        • - sortColumn, can be one of the values

          • - Grade

          • - PropertySize

          • - EstimatedCost

          • - InterconnectionQuality

        • - For non admin users, we exclude sites with grading < 50

        • - SortOrder : ascending or descending

      • - Response should be matching sites.

    • - GET /site/{id}

      • - accessed by any user

      • - response should be matching site.

    • - GET /mySites

      • - any user can access this

      • - input parameters :

        • - status

      • - returns the sites of the currently authenticated user.

      • - response should be same as GET /sites

    • - POST /sitesReviews

      • - only admin user can access this

      • - submit review of a site

      • - input are :

        • - siteId

        • - status (rejected, approved)
          - message

      • - Logic :

        • - create new siteReview record

        • - update site status

        • - clone the reviewed site in Site field

      • - response should be created sitReview record.

    • - GET /sitesReview/{site-id}

      • - input parameter is the site Id

      • - return the siteReview record associated with provided site id where createdDate is the recent on as we will have multiple siteReviews per site document.

    • - POST /sites/favorites

      • - only developer can access this

      • - input is :

        • - siteId

      • - create a SiteFavorites and associate it with the authenticated user

      • - return the created document.

    • - GET /sites/favorites

      • - only developer can access this

      • - return site favorites of logged in user

    • - POST /sites/interest

      • - only developer can access this

      • - submit site interest

      • - input parameter

        • - siteId

        • - details

        • - documents

      • - create the interest and return it in response

      • - use gridfs to store the passed in files, the model will reference the files documents.

      • - return created document

    • - GET /site/{id}/interests

      • - only admin or owner of site can access interests

      • - returns site interests of the site with child entities populated.

  • - Files endpoints

    • - GET /file/{id}

      • - any user can access this endpoint

      • - return the chunk file of the provided files id.

  • - Lookup

Pagination

In all get-all endpoints we need to enforce pagination, these endpoints should have the following parameters :

  • - offset (default 0)

  • - limit (default 10)

The parameters should be returned in the response with the total count of matching records as well, It is preferred if the default values are configurable.

Validation

Perform the following validation in each API endpoint :

  • - Path parameters :

    • - They usually represents the ID of existing objects, a validation should be done that the entity with ID exists, otherwise return error.

    • - Required input parameters in create endpoints must be present. For update endpoints we can pass only the fields that should be updated.

    • - Required input parameters should be validated against their expected type.

    • - Optional input parameters should be validated against their expected type if provided.

    • - Foreign keys must be validated.

  • - Validation between callbacks must be performed.

  • - Errors should be in json format with three fields :

    • - code : http status code

    • - status : success/failed

    • - message : reason of failure

Logging

  • - Add proper logging for method entry, method exit at INFO level.

  • - Add proper logging for input parameters, and return parameters at DEBUG level.

  • - Add proper logging for errors in ERROR level.

  • - Use watson for logging, make the logging level configurable.

Request and Response

  • - GET endpoints parameters will accept parameters as query strings, in key/value format.

  • - Create/Update endpoint parameters will accept input as JSON format.

    • - Exclude file upload endpoints which cannot work with application/json content type.

  • - Response should be in json format always.

Postman Client JSON

  • - Create postman json file listing all calls and sample data.

  • - Provide description for endpoints (recent postman version support endpoint descriptions)

  • - Get Started with Postman : http://www.getpostman.com/

Hosting

It is preferred if you provide scripts and steps to deploy the application in heroku.

Documentation

Provide a detailed README documentation for how to setup and configure the application.

Configurations

You are expected to use environment variables to store sensitive information and environment-specific configurations.    

Folder Structure and Configuration

Follow this folder structure :

  • - config/    

    • - config.js    

  • - app.js

  • - controllers/

  • - models/

  • - services/

  • - helpers/

  • - README.md

  • - env-sample (don't include .env in your submission)

  • - .. other files if needed

For configuration, we expect routes and other sensitive config will be configured in config/config.js, we prefer if you use node-config module for that. but We will leave it up to you to use the proper approach.



Final Submission Guidelines

Deliverable

  • - All source code that implement the requirement.

  • - README in markup language

  • - Verification document contains steps to verify your solution.

ELIGIBLE EVENTS:

2016 TopCoder(R) Open

Review style

Final Review

Community Review Board

Approval

User Sign-Off

ID: 30051673