diff --git a/.gitignore b/.gitignore
index 54166b9..83f1989 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,3 +3,6 @@
# Editors
.vscode/
+
+# Vim
+*.swp
diff --git a/README.md b/README.md
index 896e4cb..5436080 100644
--- a/README.md
+++ b/README.md
@@ -8,7 +8,7 @@
## π€ Why Awesome-Cheatsheets?
-I usually make a cheatsheet when I want to improve my skills on a programming language, a framework or a development tool. [I started doing these kind of things a long time ago on Gist](https://gist.github.com/LeCoupa). To better keep track of the history and to let people contribute, I reorganized all of them into this single repository. Most of the content is coming from official documentations and some books I have read.
+I usually make a cheat sheet when I want to improve my skills in a programming language, a framework or a development tool. [I started doing these kinds of things a long time ago on Gist](https://gist.github.com/LeCoupa). To better keep track of the history and to let people contribute, I reorganized all of them into this single repository. Most of the content is coming from official documentation and some books I have read.
Feel free to take a look. You might learn new things. They have been designed to provide a quick way to assess your knowledge and to save you time.
@@ -27,7 +27,10 @@ Feel free to take a look. You might learn new things. They have been designed to
- [C](languages/C.txt)
- [C#](languages/C%23.txt)
+- [Go](languages/golang.md)
+- [Java](languages/java.md)
- [PHP](languages/php.php)
+- [Python](languages/python.md)
#### Functional
@@ -50,6 +53,7 @@ Feel free to take a look. You might learn new things. They have been designed to
#### Javascript
+- [Adonis.js](backend/adonis.js)
- [Feathers.js](backend/feathers.js)
- [Moleculer](backend/moleculer.js)
- [Node.js](backend/node.js)
@@ -69,6 +73,7 @@ Feel free to take a look. You might learn new things. They have been designed to
- [React.js](frontend/react.js)
- [Vue.js](frontend/vue.js)
+- [Tailwind.css](frontend/tailwind.css)
- [Ember.js](frontend/ember.js)
- [Angular (2+)](frontend/angular.js)
- [AngularJS](frontend/angularjs.js)
@@ -79,6 +84,10 @@ Feel free to take a look. You might learn new things. They have been designed to
View cheatsheets
+#### SQL
+
+- [MySQL](databases/mysql.sh)
+
#### NoSQL
- [Redis](databases/redis.sh)
@@ -91,17 +100,30 @@ Feel free to take a look. You might learn new things. They have been designed to
#### Development
+- [cURL](tools/curl.sh)
+- [Drush](tools/drush.sh)
+- [Elasticsearch](tools/elasticsearch.js)
+- [Emmet](tools/emmet.md)
+- [Git](tools/git.sh)
+- [Puppeteer](tools/puppeteer.js)
+- [Sublime Text](tools/sublime_text.md)
- [VIM](tools/vim.txt)
+- [Visual Studio Code](tools/vscode.md)
- [Xcode](tools/xcode.txt)
#### Infrastructure
+- [AWS CLI](tools/aws.sh)
- [Docker](tools/docker.sh)
-- [Kubernetes](tools/kubernetes.sh)
+- [Heroku CLI](tools/heroku.sh)
+- [Kubernetes](tools/kubernetes.md)
- [Nanobox Boxfile](tools/nanobox_boxfile.yml)
- [Nanobox CLI](tools/nanobox_cli.sh)
+- [Nginx](tools/nginx.sh)
+- [PM2](tools/pm2.sh)
+- [Ubuntu](tools/ubuntu.sh)
## ππΌ How to Contribute?
-You are more than welcome to contribute and build your own cheatsheet for your favorite programming language, framework or development tool. Just submit changes via pull request and I will review them before merging.
+You are more than welcome to contribute and build your own cheat sheet for your favorite programming language, framework or development tool. Just submit changes via pull request and I will review them before merging.
diff --git a/backend/adonis.js b/backend/adonis.js
new file mode 100644
index 0000000..62eb1ab
--- /dev/null
+++ b/backend/adonis.js
@@ -0,0 +1,474 @@
+/********************************************************************************************
+ * ADONIS CHEATSHEET
+ * https://adonisjs.com/
+ ********************************************************************************************/
+
+/********************************************************************************************
+* AVAILABLE CLI COMMANDS
+* https://adonisjs.com/docs/ace
+********************************************************************************************/
+
+build // Compile typescript code to Javascript. Optionally watch for file changes.
+invoke // Invoke post install instructions on a given AdonisJs package.
+serve // Compile typescript code to Javascript and start the HTTP server.
+
+// Dump
+
+dump:rcfile // Dump contents of .adonisrc.json file along with defaults.
+
+// Generate
+
+generate:key // Generate a new APP_KEY secret.
+generate:manifest // Generate manifest file to execute ace commands.
+
+// List
+
+list:routes // List application routes.
+
+// Make
+
+make:command // Make a new ace command.
+make:controller // Make a new HTTP controller.
+make:middleware // Make a new middleware.
+make:migration // Make a new migration.
+make:provider // Make a new IoC container provider.
+make:validator // Make a new validator.
+make:view // Make a new view template.
+
+// Migrations
+
+migration:run // Run all pending migrations.
+migration:rollback // Rollback last set of migrations.
+migration:refresh // Rollback all migrations to the 0 batch then re-run them from the start.
+migration:reset // Rollback all migrations to the 0 batch.
+migration:status // Get the status of all the migrations.
+
+/********************************************************************************************
+* REQUEST
+* https://adonisjs.com/docs/request
+********************************************************************************************/
+
+request.all() // Returns an object containing all request data (merges query params and request body data).
+request.get() // Returns an object containing query params data.
+request.post() // Returns an object containing request body data.
+request.raw() // Returns raw body data as a string.
+request.only(['username', 'age']) // Returns an object with only the specified keys.
+request.collect(['username', 'age']) // Formats so itβs ready to save to the database.
+request.except(['csrf_token', 'submit']) // Returns an object with everything except the specified keys (opposite of only).
+request.input('drink', 'coffee') // Get the value of a given key (if it doesnβt exist, return the default value).
+
+request.headers() // Returns an object of all header data.
+request.header('some-other-header', 'default') // The header value for a given key (optionally with default value).
+
+request.cookies() // Returns an object of all cookie data.
+request.cookie('cart_total', 0) // Returns the cookie value for a given key (optionally with default value).
+request.plainCookies() // Returns an object of all raw cookie data.
+request.plainCookie('cart_total', 0) // Returns the raw cookie value for a given key (optionally with default value).
+
+request.accepts(['json', 'html']) // Reads the Accept header to help determine the response format.
+request.language(['en', 'fr']) // Language can also be negotiated based upon the Accept-Language header.
+
+request.url() // Returns the current request url.
+request.originalUrl() // Returns the full current request url with query strings.
+request.method() // Returns the HTTP request method.
+request.intended() // Returns the intended request HTTP method.
+request.ip() // Returns the most trusted ip address for the user.
+request.ips() // Returns an array of ips from most to the least trusted (removes the default ip address, which can be accessed via the ip method).
+request.subdomains() // Returns a list of request subdomains (removes www from the list).
+request.ajax() // Checks for X-Requested-With header to determine if the request is ajax or not.
+request.pjax() // This methods looks for the X-PJAX header to identify if a request is pjax or not.
+request.hostname() // Returns the request hostname.
+request.protocol() // Return the request protocol.
+request.match(['posts/:id']) // Returns whether the passed set of expressions match the current request URL.
+request.hasBody() // A boolean indicating if the request has a post body (mainly used by the BodyParser to determine whether or not to parse the body).
+request.is(['json', 'html']) // The is method returns the best matching content type for the current request. The check is entirely based upon the content-type header.
+
+/********************************************************************************************
+* RESPONSE
+* https://adonisjs.com/docs/response
+********************************************************************************************/
+
+response.header("Content-type", "application/json"); // Set a header value.
+response.safeHeader("Content-type", "application/json"); // Only set a header value if it does not already exist.
+response.removeHeader("Content-type"); // Remove an existing header.
+response.type("application/json"); // Set the Content-Type header.
+
+response.cookie("cartTotal", 20); // Set a cookie value.
+response.clearCookie("cartTotal"); // Remove an existing cookie value (by setting its expiry in the past).
+response.plainCookie("cartTotal", 20); // Set a plain cookie.
+
+response.redirect(url, [(sendParams = false)], [(status = 302)]); // Redirect request to a different url (by default it will set the status as 302).
+response.route(route, [data], [domain], [(sendParams = false)], [(status = 302)]); // Redirect to a route (via route name or controller method).
+
+response.download(filePath); // Stream the file to the client.
+response.attachment(filePath, [name], [disposition]); // Force download the file.
+
+response.continue(); // 100 status code
+response.switchingProtocols(); // 101 status code
+response.ok(); // 200 status code
+response.created(); // 201 status code
+response.accepted(); // 202 status code
+response.nonAuthoritativeInformation(); // 203 status code
+response.noContent(); // 204 status code
+response.resetContent(); // 205 status code
+response.partialContent(); // 206 status code
+response.multipleChoices(); // 300 status code
+response.movedPermanently(); // 301 status code
+response.found(); // 302 status code
+response.seeOther(); // 303 status code
+response.notModified(); // 304 status code
+response.useProxy(); // 305 status code
+response.temporaryRedirect(); // 307 status code
+response.badRequest(); // 400 status code
+response.unauthorized(); // 401 status code
+response.paymentRequired(); // 402 status code
+response.forbidden(); // 403 status code
+response.notFound(); // 404 status code
+response.methodNotAllowed(); // 405 status code
+response.notAcceptable(); // 406 status code
+response.proxyAuthenticationRequired(); // 407 status code
+response.requestTimeout(); // 408 status code
+response.conflict(); // 409 status code
+response.gone(); // 410 status code
+response.lengthRequired(); // 411 status code
+response.preconditionFailed(); // 412 status code
+response.requestEntityTooLarge(); // 413 status code
+response.requestUriTooLong(); // 414 status code
+response.unsupportedMediaType(); // 415 status code
+response.requestedRangeNotSatisfiable(); // 416 status code
+response.expectationFailed(); // 417 status code
+response.unprocessableEntity(); // 422 status code
+response.tooManyRequests(); // 429 status code
+response.internalServerError(); // 500 status code
+response.notImplemented(); // 501 status code
+response.badGateway(); // 502 status code
+response.serviceUnavailable(); // 503 status code
+response.gatewayTimeout(); // 504 status code
+response.httpVersionNotSupported(); // 505 status code
+
+/********************************************************************************************
+* ROUTING
+* https://adonisjs.com/docs/routing
+********************************************************************************************/
+
+Route.get(url, closure) // Register route for GET verb.
+Route.post(url, closure) // Register route for POST verb.
+Route.put(url, closure) // Register route for PUT verb.
+Route.patch(url, closure) // Register route for PATCH verb.
+Route.delete(url, closure) // Register route for DELETED verb.
+Route.any(url, closure) // Register route for all HTTP verbs.
+
+Route.on('/').render('welcome') // Render a view directly.
+
+Route.route('/', () => {}, ['GET', 'POST', 'PUT']) // Register route for multiple verbs.
+Route.get('users', closure).as('users.index') // Assign a unique name to the route.
+Route.get('users', closure).formats(['json', 'html'], true) // Force client to define the route format.
+
+Route.resource('users', 'UserController') // Define a resource route for CRUD operations.
+Route.resource('users', 'UserController').apiOnly() // Remove create and edit routes.
+Route.resource('users', 'UserController').only(['index']) // Keeps only the passed routes.
+Route.resource('users', 'UserController').except(['index']) //Keeps all routes except the passed routes.
+
+Route.group(() => {}) // Define a group of routes.
+Route.group(() => {}).middleware(['auth']) // Attach a middleware.
+Route.group(() => {}).formats(['json']) // Define response formats.
+Route.group(() => {}).prefix('api/v1') // Define a prefix for a group of routes.
+Route.group(() => {}).namespace('Admin') // Prefix the namespace of the bound controller.
+Route.group(() => {}).domain('blog.sthg.com') // Specify which domain goup routes belong to.
+
+/********************************************************************************************
+* VALIDATOR
+* https://indicative-v5.adonisjs.com/
+********************************************************************************************/
+
+const indicative = require("indicative");
+
+const rules = {
+ email: "required|email|unique:users",
+ password: "required|min:6|max:30",
+};
+
+// Indivative methods
+
+indicative.validate(data, rules); // Validate data with defined rules.
+indicative.validateAll(data, rules); // Same as validate but continues to validate all fields, whereas the validate method stops on first error.
+indicative.is.email(emailAddress); // Raw validator.
+indicative.extend("exists", existsFn); // Add your own rules.
+indicative.sanitize(data, rules); // Returns a new object with sanitized data:.
+indicative.sanitizor.normalizeEmail(emailAddress); // Raw sanitizor.
+
+// Validations
+
+above // Makes sure the value provided by the end user is above the expected value.
+accepted // Ensures that the field under validation is accepted.
+after // Ensures the value of the field is after the expected date.
+afterOffsetOf // Ensures the date is after a given offset of a given time period.
+alpha // Makes sure the field under validation is alpha only.
+alphaNumeric // Makes sure the field under validation is alpha numeric only.
+array // Ensure the value is a valid array. Also this validation will never validate the size of array.
+before // Ensures the value of field under validation is before a given date.
+beforeOffsetOf // Ensures the date is before a given offset of a given time period.
+boolean // Ensures the value of a field is a boolean.
+confirmed // Ensures a field value as confirmed using a _confirmation convention. This is mainly used for password confirmation field.
+date // Ensures the field under validation is a valid date. The value can be a date object or a valid date string.
+dateFormat // Ensures the date or date time is valid as the one of the defined formats.
+different // Ensures the value of the field under validation is always different from the targeted field value.
+email // Ensures the field under validation is a valid email format.
+endsWith // Ensure the value of field under validation ends with a certain substr. This validation will also trim whitespaces before making the check.
+equals // Ensures 2 values are lossely same. This validation will not check for the same type, but instead checks for the same value.
+in // Ensures the value of a given field matches one of expected values.
+includes // Ensures the value of field under validation contains a given substring.
+integer // Ensures the value is a valid integer. Also string representation of a number will return true.
+ip // Ensures the value is a valid ip address as per ipv4 and ipv6 specs.
+ipv4 // Ensures the value is a valid ip address as per ipv4 spec only.
+ipv6 // Ensures the value is a valid ip address as per ipv6 spec only.
+json // Ensures the value of field under validation is safe to be parsed using JSON.parse method.
+max // Ensures the length of a string or array is not greater than the defined length.
+min // Ensures the length of a string or array is not is not less than the expected length
+notEquals // Makes sure that the value of field under validation is not same as the defined value.
+notIn // Makes sure that the value of field under validation is not from one of the defined values.
+number // Makes sure that the value of field under validation is a valid number. The validation will pass for floats too, since it uses typeof internally.
+object // Ensures the value of field under validation is a valid Javascript object. The validation will fail for Arrays, though they are objects too in Javascript.
+range // Ensures the value of field under validation is under a given range. The values will be cased to Number automatically.
+regex // Ensures the value of field under validation, passes the regex test. The regex can be defined as a string or a RegExp object.
+required // Ensures the value of field under validation is not empty (i.e. not an empty object, empty array, empty string, null or undefined).
+requiredIf // The field is checked for required validation, when expected field exists.
+requiredWhen // The field is checked for required validation, when expected field value is same as the expected value.
+requiredWithAll // Ensures the field is required when all other fields have non-empty values.
+requiredWithAny // Ensures the field is required when any of the other fields have non-empty values.
+requiredWithoutAll // Ensures the field is required when all of the other fields has empty values.
+requiredWithoutAny // Ensures the field is required when any of the other fields has empty values.
+same // Ensures the value of 2 fields are same.
+startsWith // Ensure the value of field under validation starts with a certain substr. This validation will also trim whitespaces before making the check.
+string // Ensures the value is a string.
+under // Ensures the value of a field is under a certain value. All values will be casted to Number.
+url // Ensures the value is a valid URL format.
+
+/********************************************************************************************
+* LUCID
+* https://adonisjs.com/docs/lucid
+********************************************************************************************/
+
+Model.find() // Find a record using the primary key (always returns one record).
+Model.findOrFail() // Similar to find, but instead throws a ModelNotFoundException when unable to find a record.
+Model.findBy() // Find a record using a key/value pair (returns the first matching record).
+Model.findByOrFail() // Similar to findBy, but instead throws a ModelNotFoundException when unable to find a record.
+Model.first() // Find the first row from the database.
+Model.firstOrFail() // Similar to first, but instead throws a ModelNotFoundException when unable to find a record.
+Model.last() // Find the latest row from the database.
+Model.findOrCreate(whereAttributes, values) // Find a record, if not found a new record will be created and returned.
+Model.pick(rows = 1) // Pick x number of rows from the database table (defaults to 1 row).
+Model.pickInverse(rows = 1) // Pick x number of rows from the database table from last (defaults to 1 row).
+Model.ids() // Return an array of primary keys.
+Model.pair(lhs, rhs) // Returns an object of key/value pairs (lhs is the key, rhs is the value).
+Model.all() // Select all rows.
+Model.truncate() // Delete all rows (truncate table).
+Model.getCount() // Return a count of records in a given result set.
+Model.create(jsonAttributes) // Return model instance after saving it into the database.
+Model.createMany(arrayAttributes) // Return an array of model instances after saving them into the database.
+Model.toJSON() // Converts a serializable instance to a plain array/object.
+
+Model.query().setHidden(['password']) // Define hidden fields.
+Model.query().setVisible(['title', 'body']) // Define visible fields.
+Model.query().paginate() // Returns an object with metadata and data property that has a list of model results.
+
+instance.fill(jsonAttributes) // Remove all existing values, only set the specified attributes.
+instance.merge(jsonAttributes) // Modifies the specified attributes.
+instance.save() // Save the instance to the database.
+instance.delete() // Delete model instance from the database.
+
+instance.associate(id) // Exclusive to belongsTo relationship, where it associates two model instances together.
+instance.dissociate(id) // The opposite of associate, where you just drop the relationship
+instance.attach(arrayOfIds, callback) // Works with the belongsToMany relationship to attach a relationship inside the pivot table. The attach method accepts an optional callback receiving the pivotModel instance, allowing you to set extra properties on a pivot table if required:
+instance.detach(arrayOfIds) // The opposite of the attach method, and it removes the relationship from the pivot table only.
+
+/********************************************************************************************
+* QUERY BUILDER
+* https://adonisjs.com/docs/query-builder
+* http://knexjs.org/
+********************************************************************************************/
+
+const Database = use('Database')
+
+// Available where clauses
+
+where(~mixed~)
+orWhere(~mixed~)
+whereNot(~mixed~)
+orWhereNot(~mixed~)
+whereIn(column|columns, array|callback|builder)
+orWhereIn(column | columns, array | callback | builder)
+whereNotIn(column, array|callback|builder)
+orWhereNotIn(column, array | callback | builder)
+whereNull(column)
+orWhereNull(column)
+whereNotNull(column)
+orWhereNotNull(column)
+whereExists(builder | callback)
+orWhereExists(builder | callback)
+whereNotExists(builder | callback)
+orWhereNotExists(builder | callback)
+whereBetween(column, range)
+orWhereBetween(column, range)
+whereNotBetween(column, range)
+orWhereNotBetween(column, range)
+whereRaw(query, [bindings])
+
+/********************************************************************************************
+* DATABASE HOOKS
+* https://adonisjs.com/docs/database-hooks
+********************************************************************************************/
+
+beforeCreate // Before creating a new record.
+afterCreate // After a new record is created.
+beforeUpdate // Before updating a record.
+afterUpdate // After a record has been updated.
+beforeSave // Before creating or updating a new record.
+afterSave // After a new record has been created or updated.
+beforeDelete // Before removing a record.
+afterDelete // After a record is removed.
+afterFind // After a single record is fetched from the database.
+afterFetch // After the fetch method is executed.The hook method receives an array of model instances.
+afterPaginate // After the paginate method is executed.The hook method receives two arguments: an array of model instances and the pagination metadata.
+
+/********************************************************************************************
+* EVENTS
+* https://adonisjs.com/docs/events
+********************************************************************************************/
+
+Event.on(event, listener) // Bind single or multiple listeners for a given event. The listener can be a closure function or reference to one (or many) IoC container bindings.
+Event.when(event, listener) // The when method aliases the on method.
+Event.once(event, listener) // Same as on, but only called one time.
+Event.onAny(listener) // Bind listener for any event
+Event.times(number) // The times method is chained with on or when to limit the number of times the listener should be fired.
+Event.emit(event, data) // Emit an event with optional data.
+Event.fire(event, data) // The fire method aliases the emit method.
+Event.removeListener(event, listener) // Remove listener(s) for a given event.
+Event.off(event, listener) // The off method aliases the removeListener method.
+Event.removeAllListeners(event) // Remove all listeners for a given event.
+Event.listenersCount(event) // Return the number of listeners for a given event.
+Event.getListeners(event) // Return an array of listeners for a given event.
+Event.hasListeners(event) // Return a boolean indicating whether there are any listeners for a given event.
+
+/********************************************************************************************
+* LOGGER
+* https://adonisjs.com/docs/sessions
+********************************************************************************************/
+
+const Logger = use('Logger')
+
+Logger.level = 'debug' // Sed default config level
+
+Logger.emerg(msg[, β¦βdata]) // Print an emergency log (level 0).
+Logger.alert(msg[, β¦βdata]) // Print an alert log (level 1).
+Logger.crit(msg[, β¦βdata]) // Print a critical log (level 2).
+Logger.error(msg[, β¦βdata]) // Print an error log (level 3).
+Logger.warning(msg[, β¦βdata]) // Print a warning log (level 4).
+Logger.notice(msg[, β¦βdata]) // Print a notice log (level 5).
+Logger.info(msg[, β¦βdata]) // Print an info log (level 6).
+Logger.debug(msg[, β¦βdata]) // Print a debug log (level 7).
+
+Logger.transport(transport) // Switch transport on the fly.
+
+/********************************************************************************************
+* ENCRYPTION AND HASHING
+* https://adonisjs.com/docs/encryption-and-hashing
+********************************************************************************************/
+
+const Encryption = use('Encryption')
+
+Encryption.encrypt(string) // Encrypt a given value.
+Encryption.decrypt(string) // Decrypt an encrypted value.
+
+const Hash = use('Hash')
+
+await Hash.make(string[, config]) // Hash a plain string value.
+await Hash.verify(string, hashedString) // Since you cannot decrypt a hash, you can verify the user input against the previously hashed value.
+
+/********************************************************************************************
+* SESSIONS
+* https://adonisjs.com/docs/sessions
+********************************************************************************************/
+
+session.put(key, value); // Add a key/value pair to the session store.
+session.get(key, [defaultValue]); // Return the value for a given key (accepts an optional default value).
+session.all(); // Get everything back as an object from the session store.
+session.increment(key, [steps]); // Increment the value for a given key (ensure the previous value is a number).
+session.decrement(key, [steps]); // Decrement the value for a given key (ensure the previous value is a number).
+session.forget(key); // Remove a key/value pair from the session store.
+session.pull(key, [defaultValue]); // Return (and then remove) a key/value pair from the session store.
+session.clear(); // Empty the session store.
+
+session.flashAll() // Flash the request form data.
+session.flashOnly() // Flash only the selected fields.
+session.flashExcept() // Flash the request form data except the selected fields.
+session.withErrors() // Flash with an array of errors.
+session.flash() // Flash a custom object.
+
+/********************************************************************************************
+* FILE STORAGE
+* https://adonisjs.com/docs/file-system
+********************************************************************************************/
+
+const Drive = use('Drive')
+
+Drive.exists(relativePath) // Find if a file/directory exists or not.
+Drive.get(relativePath, encoding = utf-8) // Get file contents as a buffer or string.
+Drive.getStream(relativePath) // Get file as a stream.
+Drive.put(relativePath, content, options = {}) // Create a new file with given contents (creates any missing directories).
+Drive.prepend(relativePath, content, options = {}) // Prepend content to a file (creates a new file if path doesnβt exist).
+Drive.append(relativePath, content, options = {}) // Append content to a file (creates a new file if path doesnβt exist).
+Drive.delete(relativePath) // Remove existing file.
+Drive.move(src, dest, options = {}) // Move file from one directory to another.
+Drive.copy(src, dest, options = {}) // Copy file from one directory to another.
+
+// For S3 & Spaces drivers
+
+Drive.getObject(location, params) // Get S3 object for a given file (for params info, see S3 params).
+Drive.getUrl(location, [bucket]) // Get url for a given file (accepts optional alternative bucket param).
+Drive.getSignedUrl(location, expiry = 900, params) // Get signed url for a given file (expiry set to 15mins by default).
+
+/********************************************************************************************
+* HELPERS
+* https://adonisjs.com/docs/helpers
+********************************************************************************************/
+
+const Helpers = use('Helpers')
+
+Helpers.appRoot() // Returns path to the application root.
+Helpers.publicPath([toFile]) // Returns path to the public directory or file inside the directory.
+Helpers.configPath([toFile]) // Returns path to the config directory or file inside the directory.
+Helpers.resourcesPath([toFile]) // Returns path to the resources directory or file inside the directory.
+Helpers.migrationsPath([toFile]) // Returns path to the migrations directory or file inside the directory.
+Helpers.seedsPath([toFile]) // Returns path to the seeds directory or file inside the directory.
+Helpers.databasePath([toFile]) // Returns path to the database directory or file inside the directory.
+Helpers.viewsPath([toFile]) // Returns path to the views directory or file inside the directory.
+Helpers.tmpPath([toFile]) // Returns path to the tmp directory or file inside the directory.
+
+Helpers.promisify() // Returns promisified callback functions.
+Helpers.isAceCommand() // Returns whether the process was started as the ace command or not.
+
+/********************************************************************************************
+* SOCIAL AUTHENTICATION
+* https://adonisjs.com/docs/social-auth
+********************************************************************************************/
+
+// Drivers: Facebook, Github, Google, Instagram, Linkedin, Twitter, Foursquare.
+
+ally.redirect() // Redirect user to the 3rd party website.
+ally.getRedirectUrl() // Get redirect URL back as a string.
+ally.scope(scopesArray) // Define runtime scopes before redirecting the user.
+ally.fields(fieldsArray) // Fields to be fetched when getting the authenticated user profile.
+ally.getUser() // Get the user profile of an authenticated user (returns an AllyUser instance).
+ally.getUserByToken(accessToken, [accessSecret]) // Returns the user details using the accessToken.
+
+user.getId() // Returns the user id.
+user.getName() // Returns the user name.
+user.getEmail() // Returns the user email.
+user.getNickname() // Returns the nickname / display name of the user.
+user.getAvatar() // Returns public URL to the userβs profile picture.
+user.getAccessToken() // Returns the access token which may be used later to update the user profile.
+user.getRefreshToken() // Refresh token to be used when access token expires.
+user.getExpires() // Access token expiry data.
+user.getTokenSecret() // Returns token secret.
+user.getOriginal() // Original payload returned by the 3rd party provider.
diff --git a/backend/django.py b/backend/django.py
index 3cc384c..38b920d 100644
--- a/backend/django.py
+++ b/backend/django.py
@@ -38,15 +38,74 @@
# Use underscores in URL pattern names rather than dashes.
+# *****************************************************************************
+# Deployment
+# *****************************************************************************
+
+
+# add your media, database, venv, __pycache__ to the .gitignore (there is a compelete list that you can find here: https://github.com/jpadilla/django-project-template/blob/master/.gitignore)
+# keep migration files in the git (you will need to migrate them in target server)
+# don't run "makemigrations" in the target server (you will need to just run "migrate")
+# $ pip freeze > requirements.txt
+# make appropriate changes in your project settings.py file (change DEBUG to False and etc)
+# push your code to your git-server
+# pull your code in your target server
+# give right permissions to the web-server (e.g. $ chown www-data:www-data -R /var/www/myproject)
+# make a new venv in the target server and activate it
+# $ sudo pip install -r requirements.txt
+# sudo ./venv/bin/python3 manage.py migrate
+# restart your web-server (in case of apache: $ sudo service apache2 restart)
+
+
# *****************************************************************************
# DJANGO-ADMIN
# *****************************************************************************
-django-admin startproject # create a new project directory structure
-django-admin startapp # create a new django application with the specified name
-django-admin migrate # synchronize the database state with your current state project models and migrations
-django-admin makemigrations # create new migrations to the database based on the changes detected in the models
-django-admin runserver # start the development webserver at 127.0.0.1 with the port 8000
+django-admin check # Checks the entire django project for potential problems
+django-admin changepassword # Allows changing a userβs password. It prompts you to enter a new password twice for the given user.
+django-admin clearsessions # Can be run as a cron job or directly to clean out expired sessions.
+django-admin collectstatic # Helps to collect all the static files in the one mentioned directory
+django-admin createsuperuser # Creates a superuser account (a user who has all permissions).
+django-admin compilemessages # Compiles .po files to .mo files for use with builtin gettext support
+django-admin createcachetable # Creates the tables needed to use the SQL cache backend.
+django-admin dbshell # Runs the command-line client for specified database, or the default database if none is provided.
+django-admin diffsettings # Displays differences between the current settings.py and Django's default settings.
+django-admin dumpdata # Output the contents of the database as a fixture of the given format (using each model's default manager unless --all is specified).
+django-admin flush # Removes ALL DATA from the database, including data added during migrations. Does not achieve a "fresh install" state.
+django-admin inspectdb # Introspects the database tables in the given database and outputs a Django model module.
+django-admin loaddata # Installs the named fixture(s) in the database.
+django-admin makemessages # Runs over the entire source tree of the current directory and pulls out all strings marked for translation. It creates (or updates) a message file in the conf/locale (in the django tree) or locale (for projects and applications) directory. You must run this command with one of either the --locale, --exclude, or --all options.
django-admin help # display usage information and a list of the commands provided by each application
+django-admin makemigrations # create new migrations to the database based on the changes detected in the models
+django-admin migrate # synchronize the database state with your current state project models and migrations
+django-admin remove_stale_contenttypes # Deletes stale content types (from deleted models) in your database.y.
+django-admin runserver # start the development webserver at 127.0.0.1 with the port default 8000
+django-admin sendtestemail # Sends a test email to the email addresses specified as arguments.
+django-admin shell # Runs a Python interactive interpreter. Tries to use IPython or bpython, if one of them is available. Any standard input is executed as code.
+django-admin showmigrations # Shows all available migrations for the current project.
+django-admin sqlflush # Returns a list of the SQL statements required to return all tables in the database to the state they were in just after they were installed.
+django-admin sqlmigrate # Prints the SQL statements for the named migration.
+django-admin sqlsequencereset # Prints the SQL statements for resetting sequences for the given app name(s).
+django-admin squashmigrations # Squashes an existing set of migrations (from first until specified) into a single new one.
+django-admin startapp # create a new django application with the specified name
+django-admin startproject # create a new project directory structure
+django-admin testserver # Runs a development server with data from the given fixture(s).
django-admin version # display the current django version
+
+
+# *****************************************************************************
+# Starting a django project in python3
+# *****************************************************************************
+
+
+# 1. $ curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py; python3 get-pip.py
+# 2. $ pip install virtualenv
+# 3. $ mkdir django-projects
+# 4. $ cd django-projects
+# 5. $ virtualenv venv
+# 6. $ source venv/bin/activate
+# 7. $ pip install django
+# 8. $ django-admin startproject myproject
+# 9. $ django-admin startapp myapp
+# 10. $ python manage.py runserver
diff --git a/backend/feathers.js b/backend/feathers.js
index c1cd63e..2a574b6 100644
--- a/backend/feathers.js
+++ b/backend/feathers.js
@@ -113,13 +113,13 @@ app.service('my-service').hooks({
before: {
all: [
// Use normal functions
- function(context) { console.log('before all hook ran'); }
+ async function(context) { console.log('before all hook ran'); }
],
find: [
// Use ES6 arrow functions
context => console.log('before find hook 1 ran'),
- context => console.log('before find hook 2 ran')
+ async context => console.log('before find hook 2 ran')
],
async create (context) {
@@ -177,7 +177,8 @@ service.publish([event,] fn) // registers a publishing function for a specific
app.publish([event,] fn) // registers an event publishing callback
app.on('connection', connection => {}) // fired every time a new real-time connection is established
-app.on('login', (payload, info) => {}) // sent by the authentication module and also contains the connection in the info object that is passed as the second parameter
+app.on('disconnection', connection => {})
+app.on('login', (authenticationResult, params, context) => {}) // sent by the authentication module and also contains the connection in the info object that is passed as the second parameter
/* *******************************************************************************************
@@ -233,13 +234,6 @@ app.configure(socketio(callback)) // sets up the Socket.io t
app.configure(socketio(options [, callback])) // sets up the Socket.io transport with the given Socket.io options object and optionally calls the callback
app.configure(socketio(port, [options], [callback])) // creates a new Socket.io server on a separate port. Options and a callback are optional
-// The options can also be used to initialize uWebSocket which is a WebSocket server
-// implementation that provides better performace and reduced latency.
-// npm install uws --save
-app.configure(socketio({
- wsEngine: 'uws'
-}));
-
// --> PRIMUS <--
// https://docs.feathersjs.com/api/client/primus.html
@@ -306,55 +300,65 @@ npm install @feathersjs/authentication --save
# Wraps the passport-local authentication strategy (username and password)
npm install @feathersjs/authentication-local --save
-# Wraps the passport-jwt authentication strategy (JSON Web Token access token)
-npm install @feathersjs/authentication-jwt --save
-
-# Allows you to use any Passport OAuth1 authentication strategy (most notably Twitter)
-npm install @feathersjs/authentication-oauth1 --save
-
-# Allows you to use any Passport OAuth2 authentication strategy (FB, Instagram, Github, Google...)
-npm install @feathersjs/authentication-oauth2 --save
+# Allows to use 180+ oAuth providers (Facebook, Google, Twitter etc.)
+npm install @feathersjs/authentication-oauth --save
```
// --> SERVER <--
// https://docs.feathersjs.com/api/authentication/server.html
const options = {
- path: '/authentication', // the authentication service path
- header: 'Authorization', // the header to use when using JWT auth
- entity: 'user', // the entity that will be added to the request, socket, and context.params. (ie. req.user, socket.user, context.params.user)
- service: 'users', // the service to look up the entity
- passReqToCallback: true, // whether the request object should be passed to the strategies `verify` function
- session: false, // whether to use sessions
- cookie: {
- enabled: false, // whether cookie creation is enabled
- name: 'feathers-jwt', // the cookie name
- httpOnly: false, // when enabled, prevents the client from reading the cookie.
- secure: true // whether cookies should only be available over HTTPS
- },
- jwt: {
- header: { typ: 'access' }, // by default is an access token but can be any type
- audience: 'https://yourdomain.com', // The resource server where the token is processed
- subject: 'anonymous', // Typically the entity id associated with the JWT
- issuer: 'feathers', // The issuing server, application or resource
- algorithm: 'HS256', // the algorithm to use
- expiresIn: '1d' // the access token expiry
+ "authentication": {
+ "secret": "CHANGE_ME", // The token signing secret
+ "entity": "user", // the entity that will be added to the request, socket, and context.params. (ie. req.user, socket.user, context.params.user)
+ "service": "users", // the service to look up the entity
+ "authStrategies": [ "jwt", "local" ], // The authentication strategies to allow to create a token
+ "jwtOptions": {
+ "header": { "typ": "access" }, // by default is an access token but can be any type
+ "audience": "https://yourdomain.com", // The resource server where the token is processed
+ "issuer": "feathers", // The issuing server, application or resource
+ "algorithm": "HS256", // the algorithm to use
+ "expiresIn": "1d" // the access token expiry
+ }
}
}
-app.configure(auth(options)) // configure the authentication plugin with the given options
+const { AuthenticationService, JWTStrategy } = require('@feathersjs/authentication');
-service = app.service('authentication') // service for creating JWT (implements only the create and remove methods)
+let authService = new AuthenticationService(app);
-service.create(data) // creates a JWT based on the jwt options configured on the plugin
-service.remove(data) // removes the JWT token (mostly exists for the logout process)
-service.hooks({ before }) // registers hooks for this service
-service.hooks({ after }) // registers hooks for this service
+service.register('jwt', new JWTStrategy());
-app.passport.createJWT(payload, options) // used by the authentication service to generate JSON Web Tokens
-app.passport.verifyJWT(token, options) // verifies the signature and payload of the passed in JWT token using the options
+app.use('/authentication', authService);
+app.configure(expressOauth());
+
+app.get('defaultAuthentication') // The name of the default authentication service
+
+authService = app.service('authentication') // service for creating JWT (implements only the create and remove methods)
+
+authService.hooks({ before }) // registers hooks for this service
+authService.hooks({ after }) // registers hooks for this service
+
+new AuthenticationService(app) // Create a new authentication service
+
+class MyAuthenticationService extends AuthenticationService {} // Customize the authentication service
+
+authService.authenticate(data, params, ...strategies) // Authenticate with strategies
+authService.create(data, params) // Authenticate with data and params
+authService.create({ // Authenticate and create a JWT using the local strategy email/password
+ strategy: 'local',
+ email: 'hello@feathersjs.com',
+ password: 'supersecret'
+});
+authService.remove(id, params) // removes the JWT token (mostly exists for the logout process)
+authService.configuration // The current configuration
+authService.register(name, strategy) // Register a new authentication strategy
+authService.createAccessToken(payload) // Create a new access token with payload
+authService.verifyAccessToken(accessToken) // Verify an existing access token
+authService.getTokenOptions(authResult, params) // Get the options for a token
+authService.getPayload(authResult, params) // Return the payload for an authentication result
+authService.parse(req, res, ...strategies) // Parse an HTTP request and response with using a list of strategies
-auth.hooks.authenticate(strategies) // registers an array of authentication strategies on a service method
app.on('login', callback)) // emits an event whenever a client successfully authenticates
app.on('logout', callback)) // emits an event whenever a client successfully logout
@@ -363,198 +367,77 @@ app.on('logout', callback)) // emits an event whenever a client successfully lo
// https://docs.feathersjs.com/api/authentication/client.html
const options = {
- path: '/authentication', // the server-side authentication service path
- header: 'Authorization', // the default authorization header for REST
- jwtStrategy: 'jwt', // the name of the JWT authentication strategy
- entity: 'user', // the entity you are authenticating (ie. a users)
- service: 'users', // the service to look up the entity
- cookie: 'feathers-jwt', // the name of the cookie to parse the JWT from when cookies are enabled server side
- storageKey: 'feathers-jwt', // the key to store the accessToken in localstorage or AsyncStorage on React Native
- storage: undefined // Passing a WebStorage-compatible object to enable automatic storage on the client.
+ storage: window.localStorage, // The storage to store the access token
+ path: '/authentication', // The path of the authentication service
+ locationKey: 'access_token', // The name of the window hash parameter to parse for an access token from the window.location. Usually used by the oAuth flow.
+ locationErrorKey: 'error', // The name of the window hash parameter to parse for authentication errors. Usually used by the oAuth flow.
+ jwtStrategy: 'jwt', // The access token authentication strategy
+ storageKey: 'feathers-jwt', // Key for storing the token in e.g. localStorage
+ header: 'Authorization', // Name of the accessToken header
+ scheme: 'Bearer', // The HTTP header scheme
+ Authentication: AuthenticationClient // Allows to provide a customized authentication client class
}
app.configure(auth(options)) // configure the authentication plugin with the given options
-app.authenticate() // authenticates using the JWT from the storage
+app.reAuthenticate() // authenticates using the JWT from the storage
app.authenticate(options) // authenticate with a Feathers server by passing a strategy and other properties as credentials
app.logout() // removes the JWT accessToken from storage on the client
-app.passport.getJWT() // pulls the JWT from storage or the cookie
-app.passport.verifyJWT(token) // verifies that a JWT is not expired and decode it to get the payload
-app.passport.payloadIsValid(token) // synchronously verify that a token has not expired
+const authenticationInfo = await app.get('authentication'); // The authenticatoin information (like the user)
-app.on('authenticated', callback)) // emits an event whenever the client successfully authenticates
-app.on('logout', callback)) // emits an event whenever the client successfully authenticates
-app.on('reauthentication-error', errorHandler) // will automatically handle attempting to re-authenticate the socket when the client regains connectivity with the server
+app.on('login', callback) // emits an event whenever the client successfully authenticates
+app.on('logout', callback) // emits an event whenever the client successfully authenticates
// --> LOCAL (EMAIL & PASSWORD) <--
// https://docs.feathersjs.com/api/authentication/local.html
-const feathers = require('@feathersjs/feathers');
-const authentication = require('@feathersjs/authentication');
-const local = require('@feathersjs/authentication-local');
-const app = feathers();
+const { LocalStrategy } = require('@feathersjs/authentication-local');
const options = {
- name: 'local', // the name to use when invoking the authentication Strategy
- entity: 'user', // the entity that you're comparing username/password against
- service: 'users', // the service to look up the entity
- usernameField: 'email', // key name of username field
- passwordField: 'password', // key name of password field
- passReqToCallback: true, // whether the request object should be passed to `verify`
- session: false, // whether to use sessions
- Verifier: Verifier // A Verifier class. Defaults to the built-in one but can be a custom one
+ usernameField: 'email', // Name of the username field in the (e.g. 'email')
+ passwordField: 'password', // Name of the password field (e.g. 'password')
+ hashSize: 10, // The BCrypt hash size
+ errorMessage: 'Invalid login', // The error message to return on errors
+ entityUsernameField: usernameField, // Name of the username field on the entity if authentication request data and entity field names are different
+ entityPasswordField: passwordField // Name of the password field on the entity if authentication request data and entity field names are different
}
-app.configure(authentication(options));
-app.configure(local());
-
-// Setup a hook to only allow valid JWTs or successful
-// local auth to authenticate and get new JWT access tokens
-app.service('authentication').hooks({
- before: {
- create: [
- authentication.hooks.authenticate(['local', 'jwt'])
- ]
- }
-});
+authService.register('local', new LocalStrategy());
local.hooks.hashPassword() // hashes plain text passwords before they are saved to the database
local.hooks.protect('password') // makes sure that protected fields don't get sent to a client
-// --> JWT <--
-// https://docs.feathersjs.com/api/authentication/jwt.html
+// --> OAUTH <--
+// https://docs.feathersjs.com/api/authentication/oauth.html
+const { expressOauth, OAuthStrategy } = require('@feathersjs/authentication-oauth');
-const feathers = require('@feathersjs/feathers');
-const authentication = require('@feathersjs/authentication');
-const jwt = require('@feathersjs/authentication-jwt');
-const app = feathers();
+class GitHubStrategy extends OAuthStrategy {
+ async getEntityData(profile) {
+ const baseData = await super.getEntityData(profile);
-const options = {
- name: 'jwt', // the name to use when invoking the authentication Strategy
- entity: 'user', // the entity that you pull from if an 'id' is present in the payload
- service: 'users', // the service to look up the entity
- passReqToCallback: true, // whether the request object should be passed to `verify`
- jwtFromRequest: [ // a passport-jwt option determining where to parse the JWT
- ExtractJwt.fromHeader, // From "Authorization" header
- ExtractJwt.fromAuthHeaderWithScheme('Bearer'), // Allowing "Bearer" prefix
- ExtractJwt.fromBodyField('body') // from request body
- ],
- secretOrKey: auth.secret, // Your main secret provided to passport-jwt
- session: false, // whether to use sessions,
- Verifier: Verifier // A Verifier class. Defaults to the built-in one but can be a custom one. See below for details.
+ return {
+ ...baseData,
+ email: profile.email
+ };
+ }
}
-app.configure(authentication(options));
-app.configure(jwt());
-
-// Setup a hook to only allow valid JWTs to authenticate
-// and get new JWT access tokens
-app.service('authentication').hooks({
- before: {
- create: [
- authentication.hooks.authenticate(['jwt'])
- ]
- }
-});
-
-// --> OAUTH1 <--
-// https://docs.feathersjs.com/api/authentication/oauth1.html
-
-const feathers = require('@feathersjs/feathers');
-const authentication = require('@feathersjs/authentication');
-const jwt = require('@feathersjs/authentication-jwt');
-const oauth1 = require('@feathersjs/authentication-oauth1');
-
-const session = require('express-session');
-const TwitterStrategy = require('passport-twitter').Strategy;
-const app = feathers();
-
-// Setup in memory session
-app.use(session({
- secret: 'super secret',
- resave: true,
- saveUninitialized: true
-}));
+authService.register('github', new MyGitHubStrategy());
const options = {
- idField: 'Id', // The field to look up the entity by when logging in with the provider. Defaults to 'Id' (ie. 'twitterId').
- path: '/auth/', // The route to register the middleware
- callbackURL: 'http(s)://hostame[:port]/auth//callback', // The callback url. Will automatically take into account your host and port and whether you are in production based on your app environment to construct the url. (ie. in development http://localhost:3030/auth/twitter/callback)
- entity: 'user', // the entity that you are looking up
- service: 'users', // the service to look up the entity
- passReqToCallback: true, // whether the request object should be passed to `verify`
- session: true, // whether to use sessions,
- handler: fn, // Express middleware for handling the oauth callback. Defaults to the built in middleware.
- formatter: fn, // The response formatter. Defaults the the built in feathers-rest formatter, which returns JSON.
- Verifier: Verifier // A Verifier class. Defaults to the built-in one but can be a custom one. See below for details.
+ authentication: {
+ oauth: {
+ redirect: '/', // The redirect after a successful login
+ github: { // The per-strategy configuration
+ key: '',
+ secret: ''
+ }
+ }
+ }
}
-// Setup authentication
-app.configure(authentication(options));
-app.configure(jwt());
-app.configure(oauth1({
- name: 'twitter',
- Strategy: TwitterStrategy,
- consumerKey: '',
- consumerSecret: ''
-}));
-
-// Setup a hook to only allow valid JWTs to authenticate
-// and get new JWT access tokens
-app.service('authentication').hooks({
- before: {
- create: [
- authentication.hooks.authenticate(['jwt'])
- ]
- }
-});
-
-// --> OAUTH 2 <--
-// https://docs.feathersjs.com/api/authentication/oauth2.html
-
-const feathers = require('@feathersjs/feathers');
-const authentication = require('@feathersjs/authentication');
-const jwt = require('@feathersjs/authentication-jwt');
-const oauth2 = require('@feathersjs/authentication-oauth2');
-const FacebookStrategy = require('passport-facebook').Strategy;
-const app = feathers();
-
-const options = {
- idField: 'Id', // The field to look up the entity by when logging in with the provider. Defaults to 'Id' (ie. 'facebookId').
- path: '/auth/', // The route to register the middleware
- callbackURL: 'http(s)://hostname[:port]/auth//callback', // The callback url. Will automatically take into account your host and port and whether you are in production based on your app environment to construct the url. (ie. in development http://localhost:3030/auth/facebook/callback)
- successRedirect: undefined,
- failureRedirect: undefined,
- entity: 'user', // the entity that you are looking up
- service: 'users', // the service to look up the entity
- passReqToCallback: true, // whether the request object should be passed to `verify`
- session: false, // whether to use sessions,
- handler: fn, // Express middleware for handling the oauth callback. Defaults to the built in middleware.
- formatter: fn, // The response formatter. Defaults the the built in feathers-rest formatter, which returns JSON.
- Verifier: Verifier // A Verifier class. Defaults to the built-in one but can be a custom one. See below for details.
-}
-
-// Setup authentication
-app.configure(authentication({ secret: 'super secret' }));
-app.configure(jwt());
-app.configure(oauth2({
- name: 'facebook',
- Strategy: FacebookStrategy,
- clientID: '',
- clientSecret: '',
- scope: ['public_profile', 'email']
-}));
-
-// Setup a hook to only allow valid JWTs to authenticate
-// and get new JWT access tokens
-app.service('authentication').hooks({
- before: {
- create: [
- authentication.hooks.authenticate(['jwt'])
- ]
- }
-});
+app.configure(expressOauth(options));
/* *******************************************************************************************
@@ -602,7 +485,9 @@ app.use('/messages', service({
paginate: { // (optional) a pagination object containing a default and max page size
default: undefined, // sets the default number of items when $limit is not set
max: undefined // sets the maximum allowed number of items per page (even if the $limit query parameter is set higher)
- }
+ },
+ whitelist: [], // A list of additional non-standard query parameters to allow (e.g [ '$regex', '$populate' ])
+ multi: true // Allow create with arrays and update and remove with id null to change multiple items
}));
adapter.find() // returns a list of all records matching the query in params.query using the common querying mechanism
@@ -612,6 +497,14 @@ adapter.update(id, data, params) // completely replaces a single record identif
adapter.patch(id, data, params) // merges a record identified by id with data. id can be null to allow replacing multiple records (all records that match params.query the same as in .find). id can not be changed
adapter.remove(id, params) // removes a record identified by id. id can be null to allow removing multiple records (all records that match params.query the same as in .find)
+// Hook-less
+adapter._find()
+adapter._get(id, params)
+adapter._create(data, params)
+adapter._update(id, data, params)
+adapter._patch(id, data, params)
+adapter._remove(id, params)
+
// --> QUERYING <--
// https://docs.feathersjs.com/api/databases/querying.html
@@ -673,14 +566,13 @@ app.service('messages').find({
// β β βββ ...
// β βββ services/ # contains our services
// β β βββ ...
-// β βββ tests/ # contains Mocha test files for the app, hooks and services
-// β β βββ ...
// β β
// β βββ index.js # is used to load and start the application
// β βββ app.js # configures our Feathers application
// β βββ app.hooks.js # contains hooks which that run for all services
// β βββ channels.js # set up Feathers event channels
-// β
+// βββ tests/ # contains Mocha test files for the app, hooks and services
+// β βββ ...
// βββ .editorconfig # helps developers define and maintain consistent coding styles
// βββ .eslintrc.json # eslint configuration
// βββ package.json # express server for production
diff --git a/backend/laravel.php b/backend/laravel.php
index 70d128a..9a7f3c0 100644
--- a/backend/laravel.php
+++ b/backend/laravel.php
@@ -1,11 +1,11 @@
engine = 'InnoDB'; // Specify the table storage engine (MySQL).
+$table->charset = 'utf8'; // Specify a default character set for the table (MySQL).
+$table->collation = 'utf8_unicode_ci'; // Specify a default collation for the table (MySQL).
+$table->temporary(); // Create a temporary table (except SQL Server).
+
+// COLUMN TYPES
+
+$table->bigIncrements('id'); // Auto-incrementing UNSIGNED BIGINT (primary key) equivalent column.
+$table->bigInteger('votes'); // BIGINT equivalent column.
+$table->binary('data'); // BLOB equivalent column.
+$table->boolean('confirmed'); // BOOLEAN equivalent column.
+$table->char('name', 100); // CHAR equivalent column with an optional length.
+$table->date('created_at'); // DATE equivalent column.
+$table->dateTime('created_at'); // DATETIME equivalent column.
+$table->dateTimeTz('created_at'); // DATETIME (with timezone) equivalent column.
+$table->decimal('amount', 8, 2); // DECIMAL equivalent column with a precision (total digits) and scale (decimal digits).
+$table->double('amount', 8, 2); // DOUBLE equivalent column with a precision (total digits) and scale (decimal digits).
+$table->enum('level', ['easy', 'hard']); // ENUM equivalent column.
+$table->float('amount', 8, 2); // FLOAT equivalent column with a precision (total digits) and scale (decimal digits).
+$table->geometry('positions'); // GEOMETRY equivalent column.
+$table->geometryCollection('positions'); // GEOMETRYCOLLECTION equivalent column.
+$table->increments('id'); // Auto-incrementing UNSIGNED INTEGER (primary key) equivalent column.
+$table->integer('votes'); // INTEGER equivalent column.
+$table->ipAddress('visitor'); // IP address equivalent column.
+$table->json('options'); // JSON equivalent column.
+$table->jsonb('options'); // JSONB equivalent column.
+$table->lineString('positions'); // LINESTRING equivalent column.
+$table->longText('description'); // LONGTEXT equivalent column.
+$table->macAddress('device'); // MAC address equivalent column.
+$table->mediumIncrements('id'); // Auto-incrementing UNSIGNED MEDIUMINT (primary key) equivalent column.
+$table->mediumInteger('votes'); // MEDIUMINT equivalent column.
+$table->mediumText('description'); // MEDIUMTEXT equivalent column.
+$table->morphs('taggable'); // Adds taggable_id UNSIGNED BIGINT and taggable_type VARCHAR equivalent columns.
+$table->uuidMorphs('taggable'); // Adds taggable_id CHAR(36) and taggable_type VARCHAR(255) UUID equivalent columns.
+$table->multiLineString('positions'); // MULTILINESTRING equivalent column.
+$table->multiPoint('positions'); // MULTIPOINT equivalent column.
+$table->multiPolygon('positions'); // MULTIPOLYGON equivalent column.
+$table->nullableMorphs('taggable'); // Adds nullable versions of morphs() columns.
+$table->nullableUuidMorphs('taggable'); // Adds nullable versions of uuidMorphs() columns.
+$table->nullableTimestamps(); // Alias of timestamps() method.
+$table->point('position'); // POINT equivalent column.
+$table->polygon('positions'); // POLYGON equivalent column.
+$table->rememberToken(); // Adds a nullable remember_token VARCHAR(100) equivalent column.
+$table->set('flavors', ['strawberry', 'vanilla']); // SET equivalent column.
+$table->smallIncrements('id'); // Auto-incrementing UNSIGNED SMALLINT (primary key) equivalent column.
+$table->smallInteger('votes'); // SMALLINT equivalent column.
+$table->softDeletes(); // Adds a nullable deleted_at TIMESTAMP equivalent column for soft deletes.
+$table->softDeletesTz(); // Adds a nullable deleted_at TIMESTAMP (with timezone) equivalent column for soft deletes.
+$table->string('name', 100); // VARCHAR equivalent column with a optional length.
+$table->text('description'); // TEXT equivalent column.
+$table->time('sunrise'); // TIME equivalent column.
+$table->timeTz('sunrise'); // TIME (with timezone) equivalent column.
+$table->timestamp('added_on'); // TIMESTAMP equivalent column.
+$table->timestampTz('added_on'); // TIMESTAMP (with timezone) equivalent column.
+$table->timestamps(); // Adds nullable created_at and updated_at TIMESTAMP equivalent columns.
+$table->timestampsTz(); // Adds nullable created_at and updated_at TIMESTAMP (with timezone) equivalent columns.
+$table->tinyIncrements('id'); // Auto-incrementing UNSIGNED TINYINT (primary key) equivalent column.
+$table->tinyInteger('votes'); // TINYINT equivalent column.
+$table->unsignedBigInteger('votes'); // UNSIGNED BIGINT equivalent column.
+$table->unsignedDecimal('amount', 8, 2); // UNSIGNED DECIMAL equivalent column with a precision (total digits) and scale (decimal digits).
+$table->unsignedInteger('votes'); // UNSIGNED INTEGER equivalent column.
+$table->unsignedMediumInteger('votes'); // UNSIGNED MEDIUMINT equivalent column.
+$table->unsignedSmallInteger('votes'); // UNSIGNED SMALLINT equivalent column.
+$table->unsignedTinyInteger('votes'); // UNSIGNED TINYINT equivalent column.
+$table->uuid('id'); // UUID equivalent column.
+$table->year('birth_year'); // YEAR equivalent column.
+
+// COLUMN MODIFIERS
+
+$table->someType()->after('column'); // Place the column "after" another column (MySQL)
+$table->someType()->autoIncrement(); // Set INTEGER columns as auto-increment (primary key)
+$table->someType()->charset('utf8'); // Specify a character set for the column (MySQL)
+$table->someType()->collation('utf8_unicode_ci'); // Specify a collation for the column (MySQL/SQL Server)
+$table->someType()->comment('my comment'); // Add a comment to a column (MySQL/PostgreSQL)
+$table->someType()->default($value); // Specify a "default" value for the column
+$table->someType()->first(); // Place the column "first" in the table (MySQL)
+$table->someType()->nullable($value = true); // Allows (by default) NULL values to be inserted into the column
+$table->someType()->storedAs($expression); // Create a stored generated column (MySQL)
+$table->someType()->unsigned(); // Set INTEGER columns as UNSIGNED (MySQL)
+$table->someType()->useCurrent(); // Set TIMESTAMP columns to use CURRENT_TIMESTAMP as default value
+$table->someType()->virtualAs($expression); // Create a virtual generated column (MySQL)
+$table->someType()->generatedAs($expression); // Create an identity column with specified sequence options (PostgreSQL)
+$table->someType()->always(); // Defines the precedence of sequence values over input for an identity column (PostgreSQL)
+
+// UPDATING COLUMNS
+
+$table->someType()->change(); // Allows you to modify some existing column types to a new type or modify the column's attributes.
+$table->renameColumn('from', 'to'); // Rename a column
+
+$table->dropColumn('column'); // Drop a given column (accepts an array of columns).
+$table->dropRememberToken(); // Drop the remember_token column.
+$table->dropSoftDeletes(); // Drop the deleted_at column.
+$table->dropSoftDeletesTz(); // Alias of dropSoftDeletes() method.
+$table->dropTimestamps(); // Drop the created_at and updated_at columns.
+$table->dropTimestampsTz(); // Alias of dropTimestamps() method.
+
+// INDEXES
+
+$table->primary('id'); // Adds a primary key.
+$table->primary(['id', 'parent_id']); // Adds composite keys.
+$table->unique('email'); // Adds a unique index.
+$table->index('state'); // Adds a plain index.
+$table->spatialIndex('location'); // Adds a spatial index. (except SQLite)
+
+$table->dropPrimary('users_id_primary'); // Drop a primary key from the "users" table.
+$table->dropUnique('users_email_unique'); // Drop a unique index from the "users" table.
+$table->dropIndex('geo_state_index'); // Drop a basic index from the "geo" table.
+$table->dropSpatialIndex('geo_location_spatialindex'); // Drop a spatial index from the "geo" table (except SQLite).
+
+// FOREIGN KEY CONSTRAINTS
+
+$table->foreign('user_id')->references('id')->on('users'); // Create foreign key constraints.
+$table->dropForeign('posts_user_id_foreign'); // Drop foreign key (accepts an array of strings).
+
+Schema::enableForeignKeyConstraints(); // Enable foreign key constraints within your migrations.
+Schema::disableForeignKeyConstraints(); // Disable foreign key constraints within your migrations.
/********************************************************************************************
- * 12. COLLECTIONS
+ * COLLECTION ELOQUENT METHODS
* https://laravel.com/docs/5.7/collections
********************************************************************************************/
-
all
average
avg
@@ -321,13 +499,11 @@ whereNotInStrict
wrap
zip
-
/********************************************************************************************
- * 13. HTTP TESTS
+ * HTTP TESTS
* https://laravel.com/docs/5.7/http-tests
********************************************************************************************/
-
$response->assertStatus($code); // Assert that the response has a given code.
$response->assertForbidden(); // Assert that the response has a forbidden status code.
$response->assertNotFound(); // Assert that the response has a not found status code.
@@ -379,3 +555,32 @@ $this->assertGuest($guard = null); // Assert t
$this->assertAuthenticatedAs($user, $guard = null); // Assert that the given user is authenticated.
$this->assertCredentials(array $credentials, $guard = null); // $this->assertCredentials(array $credentials, $guard = null).
$this->assertInvalidCredentials(array $credentials, $guard = null); // Assert that the given credentials are invalid.
+
+/********************************************************************************************
+ * LARAVEL VALET COMMANDS
+ * https://laravel.com/docs/6.0/valet
+ ********************************************************************************************/
+
+valet install // Install the Valet daemon.
+valet uninstall // Uninstall the Valet daemon.
+valet use php@7.2 // Allows you to switch between php versions.
+
+valet start // Start the Valet daemon.
+valet stop // Stop the Valet daemon.
+valet restart // Restart the Valet daemon.
+
+valet park // Register your current working directory as a path which Valet should search for sites.
+valet forget // Run this command from a "parked" directory to remove it from the parked directory list.
+valet paths // View all of your "parked" paths.
+
+valet link // Link a single site in the current directory and not the entire directory.
+valet unlink // Unlink a single site in the current directory
+valet links // View all of your "linked" paths.
+
+valet secure // Serve site into https
+valet unsecure // Revert back to http
+
+valet log // View a list of logs which are written by Valet's services.
+valet trust // Add sudoers files for Brew and Valet to allow Valet commands to be run without prompting for passwords.
+valet tld // Update tld for your domains (default to test).
+valet share // Share your site with the world.
diff --git a/databases/mysql.sh b/databases/mysql.sh
new file mode 100644
index 0000000..b28b272
--- /dev/null
+++ b/databases/mysql.sh
@@ -0,0 +1,12 @@
+# *****************************************************************************
+# BASICS
+# *****************************************************************************
+
+mysqldump -h hostname -u username -p database_name -P port > file.sql # Export database
+mysql -u username -p database_name < file.sql # Import database
+
+SHOW PROCESSLIST; # Show you any queries that are currently running or in the queue to run
+
+GRANT ALL PRIVILEGES ON prospectwith.* TO 'power'@'localhost' WITH GRANT OPTION; # Grant all privileges on database
+
+CREATE USER 'newuser'@'localhost' IDENTIFIED BY 'password'; # Create user
diff --git a/databases/redis.sh b/databases/redis.sh
index 5665af4..a52f6c7 100644
--- a/databases/redis.sh
+++ b/databases/redis.sh
@@ -3,9 +3,10 @@
# *****************************************************************************
-redis-server /path/redis.conf # start redis with the related configuration file
-redis-cli # opens a redis prompt
-
+redis-server /path/redis.conf # start redis with the related configuration file
+redis-cli # opens a redis prompt
+sudo systemctl restart redis.service # Restart Redis
+sudo systemctl status redis # Check Redis status
# *****************************************************************************
# STRINGS
@@ -41,8 +42,9 @@ TTL key # returns the number of seconds until a key is
RPUSH key value [value ...] # put the new value at the end of the list
-RPUSHX key value # append a value to a list, only if the exists
+RPUSHX key value # append a value at the end of the list, only if it exists
LPUSH key value [value ...] # put the new value at the start of the list
+LPUSHX key value # append a value at the start of the list, only if it exists
LRANGE key start stop # give a subset of the list
LINDEX key index # get an element from a list by its index
LINSERT key BEFORE|AFTER pivot value # insert an element before or after another element in a list
@@ -115,7 +117,7 @@ HINCRBY key field increment # increment value in hash by X
HDEL key field [field ...] # delete one or more hash fields
HEXISTS key field # determine if a hash field exists
HKEYS key # get all the fields in a hash
-HLEN key # get all the fields in a hash
+HLEN key # get the number of fields in a hash
HSTRLEN key field # get the length of the value of a hash field
HVALS key # get all the values in a hash
diff --git a/frontend/html5.html b/frontend/html5.html
index e40173c..d090db5 100644
--- a/frontend/html5.html
+++ b/frontend/html5.html
@@ -10,28 +10,28 @@
-
+
-
-
-
+
+
+
- ...
-
-
-
-
-
+ ...
+
+
+
+
+
@@ -39,12 +39,17 @@
and
and
-
+
-
+
+
+
+
+
+
@@ -54,13 +59,13 @@
-
+
-
+
@@ -70,7 +75,7 @@