Showing preview only (215K chars total). Download the full file or copy to clipboard to get everything.
Repository: opendrops/passport
Branch: master
Commit: 237e3e5856e7
Files: 94
Total size: 191.6 KB
Directory structure:
gitextract_f4lfr0yp/
├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── config/
│ └── config.exs
├── example_app/
│ ├── .gitignore
│ ├── README.md
│ ├── brunch-config.js
│ ├── config/
│ │ ├── config.exs
│ │ ├── dev.exs
│ │ ├── prod.exs
│ │ ├── prod.secret.exs
│ │ └── test.exs
│ ├── lib/
│ │ ├── example_app/
│ │ │ ├── endpoint.ex
│ │ │ └── repo.ex
│ │ └── example_app.ex
│ ├── mix.exs
│ ├── package.json
│ ├── priv/
│ │ ├── gettext/
│ │ │ ├── en/
│ │ │ │ └── LC_MESSAGES/
│ │ │ │ └── errors.po
│ │ │ └── errors.pot
│ │ ├── repo/
│ │ │ ├── migrations/
│ │ │ │ └── 20160211110758_create_user.exs
│ │ │ └── seeds.exs
│ │ └── static/
│ │ └── robots.txt
│ ├── test/
│ │ ├── controllers/
│ │ │ └── page_controller_test.exs
│ │ ├── support/
│ │ │ ├── channel_case.ex
│ │ │ ├── conn_case.ex
│ │ │ └── model_case.ex
│ │ ├── test_helper.exs
│ │ └── views/
│ │ ├── error_view_test.exs
│ │ ├── layout_view_test.exs
│ │ └── page_view_test.exs
│ └── web/
│ ├── channels/
│ │ └── user_socket.ex
│ ├── controllers/
│ │ ├── page_controller.ex
│ │ ├── password_controller.ex
│ │ ├── registration_controller.ex
│ │ └── session_controller.ex
│ ├── gettext.ex
│ ├── models/
│ │ └── user.ex
│ ├── router.ex
│ ├── static/
│ │ ├── assets/
│ │ │ └── robots.txt
│ │ ├── css/
│ │ │ └── app.css
│ │ └── js/
│ │ ├── app.js
│ │ └── socket.js
│ ├── templates/
│ │ ├── layout/
│ │ │ └── app.html.eex
│ │ ├── page/
│ │ │ └── index.html.eex
│ │ ├── password/
│ │ │ └── forget_password.html.eex
│ │ ├── registration/
│ │ │ └── new.html.eex
│ │ └── session/
│ │ └── new.html.eex
│ ├── views/
│ │ ├── error_helpers.ex
│ │ ├── error_view.ex
│ │ ├── layout_view.ex
│ │ ├── page_view.ex
│ │ ├── password_view.ex
│ │ ├── registration_view.ex
│ │ └── session_view.ex
│ └── web.ex
├── lib/
│ ├── mix/
│ │ └── tasks/
│ │ ├── install.ex
│ │ └── passport.setup.ex
│ ├── passport/
│ │ ├── account.ex
│ │ ├── auth.ex
│ │ ├── auth_type/
│ │ │ ├── auth_type.ex
│ │ │ └── password/
│ │ │ ├── crypto.ex
│ │ │ └── password.ex
│ │ ├── config.ex
│ │ ├── plug.ex
│ │ ├── router.ex
│ │ └── session.ex
│ └── passport.ex
├── mix.exs
├── priv/
│ └── templates/
│ ├── account/
│ │ ├── account_context.ex
│ │ ├── user_migration.exs
│ │ └── user_schema.ex
│ ├── auth/
│ │ ├── auth_context.ex
│ │ ├── password_migration.exs
│ │ └── password_schema.ex
│ ├── passport.install/
│ │ ├── migration.exs
│ │ ├── model.ex
│ │ ├── password_controller.ex
│ │ ├── password_new.html.eex
│ │ ├── password_view.ex
│ │ ├── registration_controller.ex
│ │ ├── registration_new.html.eex
│ │ ├── registration_view.ex
│ │ ├── session_controller.ex
│ │ ├── session_new.html.eex
│ │ └── session_view.ex
│ └── web/
│ ├── login.html.eex
│ ├── register.html.eex
│ ├── registration_controller.ex
│ ├── registration_view.ex
│ ├── session_controller.ex
│ └── session_view.ex
└── test/
├── passport_test.exs
└── test_helper.exs
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
/_build
/cover
/deps
erl_crash.dump
*.ez
================================================
FILE: .travis.yml
================================================
language: elixir
elixir:
- 1.4.0
================================================
FILE: LICENSE
================================================
LICENSE
The MIT License
Copyright (c) 2017 Shankar Dhanasekaran and Opendrops.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
================================================
FILE: README.md
================================================
# Passport
## Experimental.
Passport is an easy to use Authentication library for Phoenix 1.3.
Passport is rewritten to make use of the context design pattern of Phoenix 1.3.
Passport organises the code in your project in the directory `lib/your_app/auth`
## Installation and Usage
1. Add passport to your list of dependencies in `mix.exs`:
def deps do
[{:passport, git: "https://github.com/opendrops/passport.git"}]
end
2. `$ mix do deps.get, compile`
3. `$ mix passport.setup`
4. Follow the instruction displayed on screen.
## State of development
This project is currently under development. Though it works, there are a lot of scope for improvement and not thoroughly tested. My goal is to make Passport a solid library for authentication. See the issues queues for the list of tasks to be done.
## License
Passport is Copyright © 2017 Opendrops. It is free software, and may be
redistributed under the terms specified in the MIT-LICENSE file.
## About Opendrops

Passport is maintained and funded by Opendrops. We love open source software! If you have a project in Elixir or Ruby, get in touch with us.
================================================
FILE: config/config.exs
================================================
# This file is responsible for configuring your application
# and its dependencies with the aid of the Mix.Config module.
use Mix.Config
# This configuration is loaded before any dependency and is restricted
# to this project. If another project depends on this project, this
# file won't be loaded nor affect the parent project. For this reason,
# if you want to provide default values for your application for
# 3rd-party users, it should be done in your "mix.exs" file.
# You can configure for your application as:
#
# config :passport, key: :value
#
# And access this configuration in your application as:
#
# Application.get_env(:passport, :key)
#
# Or configure a 3rd-party app:
#
# config :logger, level: :info
#
# It is also possible to import configuration files, relative to this
# directory. For example, you can emulate configuration per environment
# by uncommenting the line below and defining dev.exs, test.exs and such.
# Configuration from the imported file will override the ones defined
# here (which is why it is important to import them last).
#
# import_config "#{Mix.env}.exs"
================================================
FILE: example_app/.gitignore
================================================
# App artifacts
/_build
/db
/deps
/*.ez
# Generate on crash by the VM
erl_crash.dump
# Static artifacts
/node_modules
# Since we are building assets from web/static,
# we ignore priv/static. You may want to comment
# this depending on your deployment strategy.
/priv/static/
# The config/prod.secret.exs file by default contains sensitive
# data and you should not commit it into version control.
#
# Alternatively, you may comment the line below and commit the
# secrets file as long as you replace its contents by environment
# variables.
/config/prod.secret.exs
================================================
FILE: example_app/README.md
================================================
# ExampleApp
To start your Phoenix app:
1. Install dependencies with `mix deps.get`
2. Create and migrate your database with `mix ecto.create && mix ecto.migrate`
3. Start Phoenix endpoint with `mix phoenix.server`
Now you can visit [`localhost:4000`](http://localhost:4000) from your browser.
Ready to run in production? Please [check our deployment guides](http://www.phoenixframework.org/docs/deployment).
## Learn more
* Official website: http://www.phoenixframework.org/
* Guides: http://phoenixframework.org/docs/overview
* Docs: http://hexdocs.pm/phoenix
* Mailing list: http://groups.google.com/group/phoenix-talk
* Source: https://github.com/phoenixframework/phoenix
================================================
FILE: example_app/brunch-config.js
================================================
exports.config = {
// See http://brunch.io/#documentation for docs.
files: {
javascripts: {
joinTo: "js/app.js"
// To use a separate vendor.js bundle, specify two files path
// https://github.com/brunch/brunch/blob/stable/docs/config.md#files
// joinTo: {
// "js/app.js": /^(web\/static\/js)/,
// "js/vendor.js": /^(web\/static\/vendor)|(deps)/
// }
//
// To change the order of concatenation of files, explicitly mention here
// https://github.com/brunch/brunch/tree/master/docs#concatenation
// order: {
// before: [
// "web/static/vendor/js/jquery-2.1.1.js",
// "web/static/vendor/js/bootstrap.min.js"
// ]
// }
},
stylesheets: {
joinTo: "css/app.css"
},
templates: {
joinTo: "js/app.js"
}
},
conventions: {
// This option sets where we should place non-css and non-js assets in.
// By default, we set this to "/web/static/assets". Files in this directory
// will be copied to `paths.public`, which is "priv/static" by default.
assets: /^(web\/static\/assets)/
},
// Phoenix paths configuration
paths: {
// Dependencies and current project directories to watch
watched: [
"web/static",
"test/static"
],
// Where to compile files to
public: "priv/static"
},
// Configure your plugins
plugins: {
babel: {
// Do not use ES6 compiler in vendor code
ignore: [/web\/static\/vendor/]
}
},
modules: {
autoRequire: {
"js/app.js": ["web/static/js/app"]
}
},
npm: {
enabled: true,
// Whitelist the npm deps to be pulled in as front-end assets.
// All other deps in package.json will be excluded from the bundle.
whitelist: ["phoenix", "phoenix_html"]
}
};
================================================
FILE: example_app/config/config.exs
================================================
# This file is responsible for configuring your application
# and its dependencies with the aid of the Mix.Config module.
#
# This configuration file is loaded before any dependency and
# is restricted to this project.
use Mix.Config
config :passport,
resource: ExampleApp.User,
repo: ExampleApp.Repo
# Configures the endpoint
config :example_app, ExampleApp.Endpoint,
url: [host: "localhost"],
root: Path.dirname(__DIR__),
secret_key_base: "UeSmoZ4kDagwTUBmllh/+AA1Z7raiz5EG3lSHpTiOnKn0UjgIr2bZ1qxmtAdGRch",
render_errors: [accepts: ~w(html json)],
pubsub: [name: ExampleApp.PubSub,
adapter: Phoenix.PubSub.PG2]
# Configures Elixir's Logger
config :logger, :console,
format: "$time $metadata[$level] $message\n",
metadata: [:request_id]
# Import environment specific config. This must remain at the bottom
# of this file so it overrides the configuration defined above.
import_config "#{Mix.env}.exs"
# Configure phoenix generators
config :phoenix, :generators,
migration: true,
binary_id: false
================================================
FILE: example_app/config/dev.exs
================================================
use Mix.Config
# For development, we disable any cache and enable
# debugging and code reloading.
#
# The watchers configuration can be used to run external
# watchers to your application. For example, we use it
# with brunch.io to recompile .js and .css sources.
config :example_app, ExampleApp.Endpoint,
http: [port: 4000],
debug_errors: true,
code_reloader: true,
check_origin: false,
watchers: [node: ["node_modules/brunch/bin/brunch", "watch", "--stdin"]]
# Watch static and templates for browser reloading.
config :example_app, ExampleApp.Endpoint,
live_reload: [
patterns: [
~r{priv/static/.*(js|css|png|jpeg|jpg|gif|svg)$},
~r{priv/gettext/.*(po)$},
~r{web/views/.*(ex)$},
~r{web/templates/.*(eex)$}
]
]
# Do not include metadata nor timestamps in development logs
config :logger, :console, format: "[$level] $message\n"
# Set a higher stacktrace during development.
# Do not configure such in production as keeping
# and calculating stacktraces is usually expensive.
config :phoenix, :stacktrace_depth, 20
# Configure your database
config :example_app, ExampleApp.Repo,
adapter: Ecto.Adapters.Postgres,
username: "postgres",
password: "postgres",
database: "example_app_dev",
hostname: "localhost",
pool_size: 10
================================================
FILE: example_app/config/prod.exs
================================================
use Mix.Config
# For production, we configure the host to read the PORT
# from the system environment. Therefore, you will need
# to set PORT=80 before running your server.
#
# You should also configure the url host to something
# meaningful, we use this information when generating URLs.
#
# Finally, we also include the path to a manifest
# containing the digested version of static files. This
# manifest is generated by the mix phoenix.digest task
# which you typically run after static files are built.
config :example_app, ExampleApp.Endpoint,
http: [port: {:system, "PORT"}],
url: [host: "example.com", port: 80],
cache_static_manifest: "priv/static/manifest.json"
# Do not print debug messages in production
config :logger, level: :info
# ## SSL Support
#
# To get SSL working, you will need to add the `https` key
# to the previous section and set your `:url` port to 443:
#
# config :example_app, ExampleApp.Endpoint,
# ...
# url: [host: "example.com", port: 443],
# https: [port: 443,
# keyfile: System.get_env("SOME_APP_SSL_KEY_PATH"),
# certfile: System.get_env("SOME_APP_SSL_CERT_PATH")]
#
# Where those two env variables return an absolute path to
# the key and cert in disk or a relative path inside priv,
# for example "priv/ssl/server.key".
#
# We also recommend setting `force_ssl`, ensuring no data is
# ever sent via http, always redirecting to https:
#
# config :example_app, ExampleApp.Endpoint,
# force_ssl: [hsts: true]
#
# Check `Plug.SSL` for all available options in `force_ssl`.
# ## Using releases
#
# If you are doing OTP releases, you need to instruct Phoenix
# to start the server for all endpoints:
#
# config :phoenix, :serve_endpoints, true
#
# Alternatively, you can configure exactly which server to
# start per endpoint:
#
# config :example_app, ExampleApp.Endpoint, server: true
#
# You will also need to set the application root to `.` in order
# for the new static assets to be served after a hot upgrade:
#
# config :example_app, ExampleApp.Endpoint, root: "."
# Finally import the config/prod.secret.exs
# which should be versioned separately.
import_config "prod.secret.exs"
================================================
FILE: example_app/config/prod.secret.exs
================================================
use Mix.Config
# In this file, we keep production configuration that
# you likely want to automate and keep it away from
# your version control system.
config :example_app, ExampleApp.Endpoint,
secret_key_base: "Ek9P4d7ptUFZY2i3f1YvWcqBgLPbBp9RrPMKBfSvSQkAaSG+2pkEos0ol8/d1Zmo"
# Configure your database
config :example_app, ExampleApp.Repo,
adapter: Ecto.Adapters.Postgres,
username: "postgres",
password: "postgres",
database: "example_app_prod",
pool_size: 20
================================================
FILE: example_app/config/test.exs
================================================
use Mix.Config
# We don't run a server during test. If one is required,
# you can enable the server option below.
config :example_app, ExampleApp.Endpoint,
http: [port: 4001],
server: false
# Print only warnings and errors during test
config :logger, level: :warn
# Configure your database
config :example_app, ExampleApp.Repo,
adapter: Ecto.Adapters.Postgres,
username: "postgres",
password: "postgres",
database: "example_app_test",
hostname: "localhost",
pool: Ecto.Adapters.SQL.Sandbox
================================================
FILE: example_app/lib/example_app/endpoint.ex
================================================
defmodule ExampleApp.Endpoint do
use Phoenix.Endpoint, otp_app: :example_app
socket "/socket", ExampleApp.UserSocket
# Serve at "/" the static files from "priv/static" directory.
#
# You should set gzip to true if you are running phoenix.digest
# when deploying your static files in production.
plug Plug.Static,
at: "/", from: :example_app, gzip: false,
only: ~w(css fonts images js favicon.ico robots.txt)
# Code reloading can be explicitly enabled under the
# :code_reloader configuration of your endpoint.
if code_reloading? do
socket "/phoenix/live_reload/socket", Phoenix.LiveReloader.Socket
plug Phoenix.LiveReloader
plug Phoenix.CodeReloader
end
plug Plug.RequestId
plug Plug.Logger
plug Plug.Parsers,
parsers: [:urlencoded, :multipart, :json],
pass: ["*/*"],
json_decoder: Poison
plug Plug.MethodOverride
plug Plug.Head
plug Plug.Session,
store: :cookie,
key: "_example_app_key",
signing_salt: "AR9RCtl5"
plug ExampleApp.Router
end
================================================
FILE: example_app/lib/example_app/repo.ex
================================================
defmodule ExampleApp.Repo do
use Ecto.Repo, otp_app: :example_app
end
================================================
FILE: example_app/lib/example_app.ex
================================================
defmodule ExampleApp do
use Application
# See http://elixir-lang.org/docs/stable/elixir/Application.html
# for more information on OTP Applications
def start(_type, _args) do
import Supervisor.Spec, warn: false
children = [
# Start the endpoint when the application starts
supervisor(ExampleApp.Endpoint, []),
# Start the Ecto repository
supervisor(ExampleApp.Repo, []),
# Here you could define other workers and supervisors as children
# worker(ExampleApp.Worker, [arg1, arg2, arg3]),
]
# See http://elixir-lang.org/docs/stable/elixir/Supervisor.html
# for other strategies and supported options
opts = [strategy: :one_for_one, name: ExampleApp.Supervisor]
Supervisor.start_link(children, opts)
end
# Tell Phoenix to update the endpoint configuration
# whenever the application is updated.
def config_change(changed, _new, removed) do
ExampleApp.Endpoint.config_change(changed, removed)
:ok
end
end
================================================
FILE: example_app/mix.exs
================================================
defmodule ExampleApp.Mixfile do
use Mix.Project
def project do
[app: :example_app,
version: "0.0.1",
elixir: "~> 1.0",
elixirc_paths: elixirc_paths(Mix.env),
compilers: [:phoenix, :gettext] ++ Mix.compilers,
build_embedded: Mix.env == :prod,
start_permanent: Mix.env == :prod,
aliases: aliases,
deps: deps]
end
# Configuration for the OTP application.
#
# Type `mix help compile.app` for more information.
def application do
[mod: {ExampleApp, []},
applications: [:phoenix, :phoenix_html, :cowboy, :logger, :gettext,
:phoenix_ecto, :postgrex]]
end
# Specifies which paths to compile per environment.
defp elixirc_paths(:test), do: ["lib", "web", "test/support"]
defp elixirc_paths(_), do: ["lib", "web"]
# Specifies your project dependencies.
#
# Type `mix help deps` for examples and options.
defp deps do
[{:phoenix, "~> 1.1.2"},
{:phoenix_ecto, "~> 2.0"},
{:postgrex, ">= 0.0.0"},
{:phoenix_html, "~> 2.3"},
{:phoenix_live_reload, "~> 1.0", only: :dev},
{:gettext, "~> 0.9"},
{:passport, path: "../"},
{:cowboy, "~> 1.0"}]
end
# Aliases are shortcut or tasks specific to the current project.
# For example, to create, migrate and run the seeds file at once:
#
# $ mix ecto.setup
#
# See the documentation for `Mix` for more info on aliases.
defp aliases do
["ecto.setup": ["ecto.create", "ecto.migrate", "run priv/repo/seeds.exs"],
"ecto.reset": ["ecto.drop", "ecto.setup"]]
end
end
================================================
FILE: example_app/package.json
================================================
{
"repository": {
},
"dependencies": {
"babel-brunch": "^6.0.0",
"brunch": "^2.1.1",
"clean-css-brunch": ">= 1.0 < 1.8",
"css-brunch": ">= 1.0 < 1.8",
"javascript-brunch": ">= 1.0 < 1.8",
"uglify-js-brunch": ">= 1.0 < 1.8",
"phoenix": "file:deps/phoenix",
"phoenix_html": "file:deps/phoenix_html"
}
}
================================================
FILE: example_app/priv/gettext/en/LC_MESSAGES/errors.po
================================================
## `msgid`s in this file come from POT (.pot) files. Do not add, change, or
## remove `msgid`s manually here as they're tied to the ones in the
## corresponding POT file (with the same domain). Use `mix gettext.extract
## --merge` or `mix gettext.merge` to merge POT files into PO files.
msgid ""
msgstr ""
"Language: en\n"
## From Ecto.Changeset.cast/4
msgid "can't be blank"
msgstr ""
## From Ecto.Changeset.unique_constraint/3
msgid "has already been taken"
msgstr ""
## From Ecto.Changeset.put_change/3
msgid "is invalid"
msgstr ""
## From Ecto.Changeset.validate_format/3
msgid "has invalid format"
msgstr ""
## From Ecto.Changeset.validate_subset/3
msgid "has an invalid entry"
msgstr ""
## From Ecto.Changeset.validate_exclusion/3
msgid "is reserved"
msgstr ""
## From Ecto.Changeset.validate_confirmation/3
msgid "does not match confirmation"
msgstr ""
## From Ecto.Changeset.no_assoc_constraint/3
msgid "is still associated to this entry"
msgstr ""
msgid "are still associated to this entry"
msgstr ""
## From Ecto.Changeset.validate_length/3
msgid "should be %{count} character(s)"
msgid_plural "should be %{count} character(s)"
msgstr[0] ""
msgstr[1] ""
msgid "should have %{count} item(s)"
msgid_plural "should have %{count} item(s)"
msgstr[0] ""
msgstr[1] ""
msgid "should be at least %{count} character(s)"
msgid_plural "should be at least %{count} character(s)"
msgstr[0] ""
msgstr[1] ""
msgid "should have at least %{count} item(s)"
msgid_plural "should have at least %{count} item(s)"
msgstr[0] ""
msgstr[1] ""
msgid "should be at most %{count} character(s)"
msgid_plural "should be at most %{count} character(s)"
msgstr[0] ""
msgstr[1] ""
msgid "should have at most %{count} item(s)"
msgid_plural "should have at most %{count} item(s)"
msgstr[0] ""
msgstr[1] ""
## From Ecto.Changeset.validate_number/3
msgid "must be less than %{count}"
msgid_plural "must be less than %{count}"
msgstr[0] ""
msgstr[1] ""
msgid "must be greater than %{count}"
msgid_plural "must be greater than %{count}"
msgstr[0] ""
msgstr[1] ""
msgid "must be less than or equal to %{count}"
msgid_plural "must be less than or equal to %{count}"
msgstr[0] ""
msgstr[1] ""
msgid "must be greater than or equal to %{count}"
msgid_plural "must be greater than or equal to %{count}"
msgstr[0] ""
msgstr[1] ""
msgid "must be equal to %{count}"
msgid_plural "must be equal to %{count}"
msgstr[0] ""
msgstr[1] ""
================================================
FILE: example_app/priv/gettext/errors.pot
================================================
## This file is a PO Template file. `msgid`s here are often extracted from
## source code; add new translations manually only if they're dynamic
## translations that can't be statically extracted. Run `mix
## gettext.extract` to bring this file up to date. Leave `msgstr`s empty as
## changing them here as no effect; edit them in PO (`.po`) files instead.
## From Ecto.Changeset.cast/4
msgid "can't be blank"
msgstr ""
## From Ecto.Changeset.unique_constraint/3
msgid "has already been taken"
msgstr ""
## From Ecto.Changeset.put_change/3
msgid "is invalid"
msgstr ""
## From Ecto.Changeset.validate_format/3
msgid "has invalid format"
msgstr ""
## From Ecto.Changeset.validate_subset/3
msgid "has an invalid entry"
msgstr ""
## From Ecto.Changeset.validate_exclusion/3
msgid "is reserved"
msgstr ""
## From Ecto.Changeset.validate_confirmation/3
msgid "does not match confirmation"
msgstr ""
## From Ecto.Changeset.no_assoc_constraint/3
msgid "is still associated to this entry"
msgstr ""
msgid "are still associated to this entry"
msgstr ""
## From Ecto.Changeset.validate_length/3
msgid "should be %{count} character(s)"
msgid_plural "should be %{count} character(s)"
msgstr[0] ""
msgstr[1] ""
msgid "should have %{count} item(s)"
msgid_plural "should have %{count} item(s)"
msgstr[0] ""
msgstr[1] ""
msgid "should be at least %{count} character(s)"
msgid_plural "should be at least %{count} character(s)"
msgstr[0] ""
msgstr[1] ""
msgid "should have at least %{count} item(s)"
msgid_plural "should have at least %{count} item(s)"
msgstr[0] ""
msgstr[1] ""
msgid "should be at most %{count} character(s)"
msgid_plural "should be at most %{count} character(s)"
msgstr[0] ""
msgstr[1] ""
msgid "should have at most %{count} item(s)"
msgid_plural "should have at most %{count} item(s)"
msgstr[0] ""
msgstr[1] ""
## From Ecto.Changeset.validate_number/3
msgid "must be less than %{count}"
msgid_plural "must be less than %{count}"
msgstr[0] ""
msgstr[1] ""
msgid "must be greater than %{count}"
msgid_plural "must be greater than %{count}"
msgstr[0] ""
msgstr[1] ""
msgid "must be less than or equal to %{count}"
msgid_plural "must be less than or equal to %{count}"
msgstr[0] ""
msgstr[1] ""
msgid "must be greater than or equal to %{count}"
msgid_plural "must be greater than or equal to %{count}"
msgstr[0] ""
msgstr[1] ""
msgid "must be equal to %{count}"
msgid_plural "must be equal to %{count}"
msgstr[0] ""
msgstr[1] ""
================================================
FILE: example_app/priv/repo/migrations/20160211110758_create_user.exs
================================================
defmodule ExampleApp.Repo.Migrations.CreateUser do
use Ecto.Migration
def change do
create table(:users) do
add :name, :string
add :email, :string, null: false
add :password_hash, :string
timestamps
end
create unique_index(:users, [:email])
end
end
================================================
FILE: example_app/priv/repo/seeds.exs
================================================
# Script for populating the database. You can run it as:
#
# mix run priv/repo/seeds.exs
#
# Inside the script, you can read and write to any of your
# repositories directly:
#
# ExampleApp.Repo.insert!(%ExampleApp.SomeModel{})
#
# We recommend using the bang functions (`insert!`, `update!`
# and so on) as they will fail if something goes wrong.
================================================
FILE: example_app/priv/static/robots.txt
================================================
# See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file
#
# To ban all spiders from the entire site uncomment the next two lines:
# User-agent: *
# Disallow: /
================================================
FILE: example_app/test/controllers/page_controller_test.exs
================================================
defmodule ExampleApp.PageControllerTest do
use ExampleApp.ConnCase
test "GET /", %{conn: conn} do
conn = get conn, "/"
assert html_response(conn, 200) =~ "Welcome to Phoenix!"
end
end
================================================
FILE: example_app/test/support/channel_case.ex
================================================
defmodule ExampleApp.ChannelCase do
@moduledoc """
This module defines the test case to be used by
channel tests.
Such tests rely on `Phoenix.ChannelTest` and also
imports other functionality to make it easier
to build and query models.
Finally, if the test case interacts with the database,
it cannot be async. For this reason, every test runs
inside a transaction which is reset at the beginning
of the test unless the test case is marked as async.
"""
use ExUnit.CaseTemplate
using do
quote do
# Import conveniences for testing with channels
use Phoenix.ChannelTest
alias ExampleApp.Repo
import Ecto
import Ecto.Changeset
import Ecto.Query, only: [from: 1, from: 2]
# The default endpoint for testing
@endpoint ExampleApp.Endpoint
end
end
setup tags do
unless tags[:async] do
Ecto.Adapters.SQL.restart_test_transaction(ExampleApp.Repo, [])
end
:ok
end
end
================================================
FILE: example_app/test/support/conn_case.ex
================================================
defmodule ExampleApp.ConnCase do
@moduledoc """
This module defines the test case to be used by
tests that require setting up a connection.
Such tests rely on `Phoenix.ConnTest` and also
imports other functionality to make it easier
to build and query models.
Finally, if the test case interacts with the database,
it cannot be async. For this reason, every test runs
inside a transaction which is reset at the beginning
of the test unless the test case is marked as async.
"""
use ExUnit.CaseTemplate
using do
quote do
# Import conveniences for testing with connections
use Phoenix.ConnTest
alias ExampleApp.Repo
import Ecto
import Ecto.Changeset
import Ecto.Query, only: [from: 1, from: 2]
import ExampleApp.Router.Helpers
# The default endpoint for testing
@endpoint ExampleApp.Endpoint
end
end
setup tags do
unless tags[:async] do
Ecto.Adapters.SQL.restart_test_transaction(ExampleApp.Repo, [])
end
{:ok, conn: Phoenix.ConnTest.conn()}
end
end
================================================
FILE: example_app/test/support/model_case.ex
================================================
defmodule ExampleApp.ModelCase do
@moduledoc """
This module defines the test case to be used by
model tests.
You may define functions here to be used as helpers in
your model tests. See `errors_on/2`'s definition as reference.
Finally, if the test case interacts with the database,
it cannot be async. For this reason, every test runs
inside a transaction which is reset at the beginning
of the test unless the test case is marked as async.
"""
use ExUnit.CaseTemplate
using do
quote do
alias ExampleApp.Repo
import Ecto
import Ecto.Changeset
import Ecto.Query, only: [from: 1, from: 2]
import ExampleApp.ModelCase
end
end
setup tags do
unless tags[:async] do
Ecto.Adapters.SQL.restart_test_transaction(ExampleApp.Repo, [])
end
:ok
end
@doc """
Helper for returning list of errors in model when passed certain data.
## Examples
Given a User model that lists `:name` as a required field and validates
`:password` to be safe, it would return:
iex> errors_on(%User{}, %{password: "password"})
[password: "is unsafe", name: "is blank"]
You could then write your assertion like:
assert {:password, "is unsafe"} in errors_on(%User{}, %{password: "password"})
You can also create the changeset manually and retrieve the errors
field directly:
iex> changeset = User.changeset(%User{}, password: "password")
iex> {:password, "is unsafe"} in changeset.errors
true
"""
def errors_on(model, data) do
model.__struct__.changeset(model, data).errors
end
end
================================================
FILE: example_app/test/test_helper.exs
================================================
ExUnit.start
Mix.Task.run "ecto.create", ~w(-r ExampleApp.Repo --quiet)
Mix.Task.run "ecto.migrate", ~w(-r ExampleApp.Repo --quiet)
Ecto.Adapters.SQL.begin_test_transaction(ExampleApp.Repo)
================================================
FILE: example_app/test/views/error_view_test.exs
================================================
defmodule ExampleApp.ErrorViewTest do
use ExampleApp.ConnCase, async: true
# Bring render/3 and render_to_string/3 for testing custom views
import Phoenix.View
test "renders 404.html" do
assert render_to_string(ExampleApp.ErrorView, "404.html", []) ==
"Page not found"
end
test "render 500.html" do
assert render_to_string(ExampleApp.ErrorView, "500.html", []) ==
"Server internal error"
end
test "render any other" do
assert render_to_string(ExampleApp.ErrorView, "505.html", []) ==
"Server internal error"
end
end
================================================
FILE: example_app/test/views/layout_view_test.exs
================================================
defmodule ExampleApp.LayoutViewTest do
use ExampleApp.ConnCase, async: true
end
================================================
FILE: example_app/test/views/page_view_test.exs
================================================
defmodule ExampleApp.PageViewTest do
use ExampleApp.ConnCase, async: true
end
================================================
FILE: example_app/web/channels/user_socket.ex
================================================
defmodule ExampleApp.UserSocket do
use Phoenix.Socket
## Channels
# channel "rooms:*", ExampleApp.RoomChannel
## Transports
transport :websocket, Phoenix.Transports.WebSocket
# transport :longpoll, Phoenix.Transports.LongPoll
# Socket params are passed from the client and can
# be used to verify and authenticate a user. After
# verification, you can put default assigns into
# the socket that will be set for all channels, ie
#
# {:ok, assign(socket, :user_id, verified_user_id)}
#
# To deny connection, return `:error`.
#
# See `Phoenix.Token` documentation for examples in
# performing token verification on connect.
def connect(_params, socket) do
{:ok, socket}
end
# Socket id's are topics that allow you to identify all sockets for a given user:
#
# def id(socket), do: "users_socket:#{socket.assigns.user_id}"
#
# Would allow you to broadcast a "disconnect" event and terminate
# all active sockets and channels for a given user:
#
# ExampleApp.Endpoint.broadcast("users_socket:#{user.id}", "disconnect", %{})
#
# Returning `nil` makes this socket anonymous.
def id(_socket), do: nil
end
================================================
FILE: example_app/web/controllers/page_controller.ex
================================================
defmodule ExampleApp.PageController do
use ExampleApp.Web, :controller
def index(conn, _params) do
render conn, "index.html"
end
end
================================================
FILE: example_app/web/controllers/password_controller.ex
================================================
defmodule ExampleApp.PasswordController do
use ExampleApp.Web, :controller
alias ExampleApp.User
def forget_password(conn, _) do
conn
|> render(:forget_password)
end
def reset_password(conn, %{"user" => %{"email" => email}}) do
conn
|> put_flash(:info, "Password reset link has been sent to your email address.")
|> redirect(to: session_path(conn, :new))
end
end
================================================
FILE: example_app/web/controllers/registration_controller.ex
================================================
defmodule ExampleApp.RegistrationController do
use ExampleApp.Web, :controller
alias ExampleApp.User
def new(conn, _params) do
changeset = User.changeset(%ExampleApp.User{})
conn
|> render(:new, changeset: changeset)
end
def create(conn, %{"user" => registration_params}) do
changeset = User.registration_changeset(%User{}, registration_params)
case Repo.insert(changeset) do
{:ok, user} ->
conn
|> put_flash(:info, "Account created!")
|> redirect(to: page_path(conn, :index))
{:error, changeset} ->
conn
|> render(:new, changeset: changeset)
end
end
end
================================================
FILE: example_app/web/controllers/session_controller.ex
================================================
defmodule ExampleApp.SessionController do
use ExampleApp.Web, :controller
alias ExampleApp.User
alias Passport.Session
def new(conn, _) do
conn
|> render(:new)
end
def create(conn, %{"session" => %{"email" => email, "password" => pass}}) do
case Session.login(conn, email, pass) do
{:ok, conn} ->
conn
|> put_flash(:info, "Welcome back!")
|> redirect(to: page_path(conn, :index))
{:error, _reason, conn} ->
conn
|> put_flash(:error, "Invalid username/password combination")
|> render(:new)
end
end
def delete(conn, _) do
conn
|> Session.logout()
|> put_flash(:info, "You have been logged out")
|> redirect(to: session_path(conn, :new))
end
end
================================================
FILE: example_app/web/gettext.ex
================================================
defmodule ExampleApp.Gettext do
@moduledoc """
A module providing Internationalization with a gettext-based API.
By using [Gettext](http://hexdocs.pm/gettext),
your module gains a set of macros for translations, for example:
import ExampleApp.Gettext
# Simple translation
gettext "Here is the string to translate"
# Plural translation
ngettext "Here is the string to translate",
"Here are the strings to translate",
3
# Domain-based translation
dgettext "errors", "Here is the error message to translate"
See the [Gettext Docs](http://hexdocs.pm/gettext) for detailed usage.
"""
use Gettext, otp_app: :example_app
end
================================================
FILE: example_app/web/models/user.ex
================================================
defmodule ExampleApp.User do
use ExampleApp.Web, :model
alias Passport.Password
schema "users" do
field :email, :string
field :password, :string, virtual: true
field :password_hash, :string
timestamps
end
def changeset(model, params \\ :empty) do model
|> cast(params, ~w(email), [])
|> validate_length(:email, min: 1, max: 150)
|> unique_constraint(:email)
end
def registration_changeset(model, params) do model
|> changeset(params)
|> cast(params, ~w(password), [])
|> validate_length(:password, min: 6, max: 100)
|> put_hashed_password()
end
defp put_hashed_password(changeset) do
case changeset do
%Ecto.Changeset{valid?: true, changes: %{password: pass}} ->
put_change(changeset, :password_hash, Password.hash(pass))
_ ->
changeset
end
end
end
================================================
FILE: example_app/web/router.ex
================================================
defmodule ExampleApp.Router do
use ExampleApp.Web, :router
use Passport
pipeline :browser do
plug :accepts, ["html"]
plug :fetch_session
plug :fetch_flash
plug :protect_from_forgery
plug :put_secure_browser_headers
plug :current_user
end
pipeline :api do
plug :accepts, ["json"]
end
scope "/", ExampleApp do
pipe_through :browser # Use the default browser stack
get "/", PageController, :index
get "/login", SessionController, :new
post "/login", SessionController, :create
get "/logout", SessionController, :delete
get "/register", RegistrationController, :new
post "/register", RegistrationController, :create
get "/forget-password", PasswordController, :forget_password
post "/reset-password", PasswordController, :reset_password
end
# Other scopes may use custom stacks.
# scope "/api", ExampleApp do
# pipe_through :api
# end
end
================================================
FILE: example_app/web/static/assets/robots.txt
================================================
# See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file
#
# To ban all spiders from the entire site uncomment the next two lines:
# User-agent: *
# Disallow: /
================================================
FILE: example_app/web/static/css/app.css
================================================
/*!
* Bootstrap v3.3.5 (http://getbootstrap.com)
* Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
*//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid silver}legend{padding:0;border:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-spacing:0;border-collapse:collapse}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,:after,:before{color:#000!important;text-shadow:none!important;background:0 0!important;-webkit-box-shadow:none!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #ddd!important}}@font-face{font-family:'Glyphicons Halflings';src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(../fonts/glyphicons-halflings-regular.woff2) format('woff2'),url(../fonts/glyphicons-halflings-regular.woff) format('woff'),url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\2a"}.glyphicon-plus:before{content:"\2b"}.glyphicon-eur:before,.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-jpy:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}:after,:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:focus,a:hover{color:#23527c;text-decoration:underline}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.carousel-inner>.item>a>img,.carousel-inner>.item>img,.img-responsive,.thumbnail a>img,.thumbnail>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{display:inline-block;max-width:100%;height:auto;padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role=button]{cursor:pointer}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-weight:400;line-height:1;color:#777}.h1,.h2,.h3,h1,h2,h3{margin-top:20px;margin-bottom:10px}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small{font-size:65%}.h4,.h5,.h6,h4,h5,h6{margin-top:10px;margin-bottom:10px}.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-size:75%}.h1,h1{font-size:36px}.h2,h2{font-size:30px}.h3,h3{font-size:24px}.h4,h4{font-size:18px}.h5,h5{font-size:14px}.h6,h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}.small,small{font-size:85%}.mark,mark{padding:.2em;background-color:#fcf8e3}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab7}a.text-primary:focus,a.text-primary:hover{color:#286090}.text-success{color:#3c763d}a.text-success:focus,a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:focus,a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:focus,a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:focus,a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:focus,a.bg-primary:hover{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:focus,a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:focus,a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:focus,a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:focus,a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ol,ul{margin-top:0;margin-bottom:10px}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;margin-left:-5px;list-style:none}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-top:0;margin-bottom:20px}dd,dt{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[data-original-title],abbr[title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote ol:last-child,blockquote p:last-child,blockquote ul:last-child{margin-bottom:0}blockquote .small,blockquote footer,blockquote small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote .small:before,blockquote footer:before,blockquote small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;text-align:right;border-right:5px solid #eee;border-left:0}.blockquote-reverse .small:before,.blockquote-reverse footer:before,.blockquote-reverse small:before,blockquote.pull-right .small:before,blockquote.pull-right footer:before,blockquote.pull-right small:before{content:''}.blockquote-reverse .small:after,.blockquote-reverse footer:after,.blockquote-reverse small:after,blockquote.pull-right .small:after,blockquote.pull-right footer:after,blockquote.pull-right small:after{content:'\00A0 \2014'}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;font-weight:700;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{margin-right:-15px;margin-left:-15px}.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>tbody>tr>td,.table>tbody>tr>th,.table>tfoot>tr>td,.table>tfoot>tr>th,.table>thead>tr>td,.table>thead>tr>th{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>td,.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>td,.table>thead:first-child>tr:first-child>th{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>tbody>tr>td,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>td,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>thead>tr>th{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>tbody>tr>td,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>td,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border:1px solid #ddd}.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*=col-]{position:static;display:table-column;float:none}table td[class*=col-],table th[class*=col-]{position:static;display:table-cell;float:none}.table>tbody>tr.active>td,.table>tbody>tr.active>th,.table>tbody>tr>td.active,.table>tbody>tr>th.active,.table>tfoot>tr.active>td,.table>tfoot>tr.active>th,.table>tfoot>tr>td.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>thead>tr.active>th,.table>thead>tr>td.active,.table>thead>tr>th.active{background-color:#f5f5f5}.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover{background-color:#e8e8e8}.table>tbody>tr.success>td,.table>tbody>tr.success>th,.table>tbody>tr>td.success,.table>tbody>tr>th.success,.table>tfoot>tr.success>td,.table>tfoot>tr.success>th,.table>tfoot>tr>td.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>thead>tr.success>th,.table>thead>tr>td.success,.table>thead>tr>th.success{background-color:#dff0d8}.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover{background-color:#d0e9c6}.table>tbody>tr.info>td,.table>tbody>tr.info>th,.table>tbody>tr>td.info,.table>tbody>tr>th.info,.table>tfoot>tr.info>td,.table>tfoot>tr.info>th,.table>tfoot>tr>td.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>thead>tr.info>th,.table>thead>tr>td.info,.table>thead>tr>th.info{background-color:#d9edf7}.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover{background-color:#c4e3f3}.table>tbody>tr.warning>td,.table>tbody>tr.warning>th,.table>tbody>tr>td.warning,.table>tbody>tr>th.warning,.table>tfoot>tr.warning>td,.table>tfoot>tr.warning>th,.table>tfoot>tr>td.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>thead>tr.warning>th,.table>thead>tr>td.warning,.table>thead>tr>th.warning{background-color:#fcf8e3}.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover{background-color:#faf2cc}.table>tbody>tr.danger>td,.table>tbody>tr.danger>th,.table>tbody>tr>td.danger,.table>tbody>tr>th.danger,.table>tfoot>tr.danger>td,.table>tfoot>tr.danger>th,.table>tfoot>tr>td.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>thead>tr.danger>th,.table>thead>tr>td.danger,.table>thead>tr>th.danger{background-color:#f2dede}.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover{background-color:#ebcccc}.table-responsive{min-height:.01%;overflow-x:auto}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>td,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>thead>tr>th{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=checkbox],input[type=radio]{margin:4px 0 0;margin-top:1px\9;line-height:normal}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=file]:focus,input[type=checkbox]:focus,input[type=radio]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}input[type=search]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type=date].form-control,input[type=time].form-control,input[type=datetime-local].form-control,input[type=month].form-control{line-height:34px}.input-group-sm input[type=date],.input-group-sm input[type=time],.input-group-sm input[type=datetime-local],.input-group-sm input[type=month],input[type=date].input-sm,input[type=time].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm{line-height:30px}.input-group-lg input[type=date],.input-group-lg input[type=time],.input-group-lg input[type=datetime-local],.input-group-lg input[type=month],input[type=date].input-lg,input[type=time].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg{line-height:46px}}.form-group{margin-bottom:15px}.checkbox,.radio{position:relative;display:block;margin-top:10px;margin-bottom:10px}.checkbox label,.radio label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox],.radio input[type=radio],.radio-inline input[type=radio]{position:absolute;margin-top:4px\9;margin-left:-20px}.checkbox+.checkbox,.radio+.radio{margin-top:-5px}.checkbox-inline,.radio-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.checkbox-inline+.checkbox-inline,.radio-inline+.radio-inline{margin-top:0;margin-left:10px}fieldset[disabled] input[type=checkbox],fieldset[disabled] input[type=radio],input[type=checkbox].disabled,input[type=checkbox][disabled],input[type=radio].disabled,input[type=radio][disabled]{cursor:not-allowed}.checkbox-inline.disabled,.radio-inline.disabled,fieldset[disabled] .checkbox-inline,fieldset[disabled] .radio-inline{cursor:not-allowed}.checkbox.disabled label,.radio.disabled label,fieldset[disabled] .checkbox label,fieldset[disabled] .radio label{cursor:not-allowed}.form-control-static{min-height:34px;padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-right:0;padding-left:0}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}select[multiple].input-sm,textarea.input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.form-group-sm select.form-control{height:30px;line-height:30px}.form-group-sm select[multiple].form-control,.form-group-sm textarea.form-control{height:auto}.form-group-sm .form-control-static{height:30px;min-height:32px;padding:6px 10px;font-size:12px;line-height:1.5}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-lg{height:46px;line-height:46px}select[multiple].input-lg,textarea.input-lg{height:auto}.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.form-group-lg select.form-control{height:46px;line-height:46px}.form-group-lg select[multiple].form-control,.form-group-lg textarea.form-control{height:auto}.form-group-lg .form-control-static{height:46px;min-height:38px;padding:11px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.form-group-lg .form-control+.form-control-feedback,.input-group-lg+.form-control-feedback,.input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px}.form-group-sm .form-control+.form-control-feedback,.input-group-sm+.form-control-feedback,.input-sm+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .checkbox,.has-success .checkbox-inline,.has-success .control-label,.has-success .help-block,.has-success .radio,.has-success .radio-inline,.has-success.checkbox label,.has-success.checkbox-inline label,.has-success.radio label,.has-success.radio-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.has-success .form-control-feedback{color:#3c763d}.has-warning .checkbox,.has-warning .checkbox-inline,.has-warning .control-label,.has-warning .help-block,.has-warning .radio,.has-warning .radio-inline,.has-warning.checkbox label,.has-warning.checkbox-inline label,.has-warning.radio label,.has-warning.radio-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .checkbox,.has-error .checkbox-inline,.has-error .control-label,.has-error .help-block,.has-error .radio,.has-error .radio-inline,.has-error.checkbox label,.has-error.checkbox-inline label,.has-error.radio label,.has-error.radio-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .form-control,.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .checkbox,.form-inline .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .checkbox label,.form-inline .radio label{padding-left:0}.form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .checkbox,.form-horizontal .checkbox-inline,.form-horizontal .radio,.form-horizontal .radio-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .checkbox,.form-horizontal .radio{min-height:27px}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.form-horizontal .control-label{padding-top:7px;margin-bottom:0;text-align:right}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:14.33px;font-size:18px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px;font-size:12px}}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:400;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-image:none;border:1px solid transparent;border-radius:4px}.btn.active.focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn:active:focus,.btn:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.focus,.btn:focus,.btn:hover{color:#333;text-decoration:none}.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none;opacity:.65}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default.focus,.btn-default:focus{color:#333;background-color:#e6e6e6;border-color:#8c8c8c}.btn-default:hover{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active.focus,.btn-default.active:focus,.btn-default.active:hover,.btn-default:active.focus,.btn-default:active:focus,.btn-default:active:hover,.open>.dropdown-toggle.btn-default.focus,.open>.dropdown-toggle.btn-default:focus,.open>.dropdown-toggle.btn-default:hover{color:#333;background-color:#d4d4d4;border-color:#8c8c8c}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled,.btn-default.disabled.active,.btn-default.disabled.focus,.btn-default.disabled:active,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled],.btn-default[disabled].active,.btn-default[disabled].focus,.btn-default[disabled]:active,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default,fieldset[disabled] .btn-default.active,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:active,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary.focus,.btn-primary:focus{color:#fff;background-color:#286090;border-color:#122b40}.btn-primary:hover{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active.focus,.btn-primary.active:focus,.btn-primary.active:hover,.btn-primary:active.focus,.btn-primary:active:focus,.btn-primary:active:hover,.open>.dropdown-toggle.btn-primary.focus,.open>.dropdown-toggle.btn-primary:focus,.open>.dropdown-toggle.btn-primary:hover{color:#fff;background-color:#204d74;border-color:#122b40}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled,.btn-primary.disabled.active,.btn-primary.disabled.focus,.btn-primary.disabled:active,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled],.btn-primary[disabled].active,.btn-primary[disabled].focus,.btn-primary[disabled]:active,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-primary.active,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:active,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success.focus,.btn-success:focus{color:#fff;background-color:#449d44;border-color:#255625}.btn-success:hover{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active.focus,.btn-success.active:focus,.btn-success.active:hover,.btn-success:active.focus,.btn-success:active:focus,.btn-success:active:hover,.open>.dropdown-toggle.btn-success.focus,.open>.dropdown-toggle.btn-success:focus,.open>.dropdown-toggle.btn-success:hover{color:#fff;background-color:#398439;border-color:#255625}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled,.btn-success.disabled.active,.btn-success.disabled.focus,.btn-success.disabled:active,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled],.btn-success[disabled].active,.btn-success[disabled].focus,.btn-success[disabled]:active,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success,fieldset[disabled] .btn-success.active,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:active,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info.focus,.btn-info:focus{color:#fff;background-color:#31b0d5;border-color:#1b6d85}.btn-info:hover{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active.focus,.btn-info.active:focus,.btn-info.active:hover,.btn-info:active.focus,.btn-info:active:focus,.btn-info:active:hover,.open>.dropdown-toggle.btn-info.focus,.open>.dropdown-toggle.btn-info:focus,.open>.dropdown-toggle.btn-info:hover{color:#fff;background-color:#269abc;border-color:#1b6d85}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled,.btn-info.disabled.active,.btn-info.disabled.focus,.btn-info.disabled:active,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled],.btn-info[disabled].active,.btn-info[disabled].focus,.btn-info[disabled]:active,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info,fieldset[disabled] .btn-info.active,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:active,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning.focus,.btn-warning:focus{color:#fff;background-color:#ec971f;border-color:#985f0d}.btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active.focus,.btn-warning.active:focus,.btn-warning.active:hover,.btn-warning:active.focus,.btn-warning:active:focus,.btn-warning:active:hover,.open>.dropdown-toggle.btn-warning.focus,.open>.dropdown-toggle.btn-warning:focus,.open>.dropdown-toggle.btn-warning:hover{color:#fff;background-color:#d58512;border-color:#985f0d}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled,.btn-warning.disabled.active,.btn-warning.disabled.focus,.btn-warning.disabled:active,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled],.btn-warning[disabled].active,.btn-warning[disabled].focus,.btn-warning[disabled]:active,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning,fieldset[disabled] .btn-warning.active,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:active,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger.focus,.btn-danger:focus{color:#fff;background-color:#c9302c;border-color:#761c19}.btn-danger:hover{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active.focus,.btn-danger.active:focus,.btn-danger.active:hover,.btn-danger:active.focus,.btn-danger:active:focus,.btn-danger:active:hover,.open>.dropdown-toggle.btn-danger.focus,.open>.dropdown-toggle.btn-danger:focus,.open>.dropdown-toggle.btn-danger:hover{color:#fff;background-color:#ac2925;border-color:#761c19}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled,.btn-danger.disabled.active,.btn-danger.disabled.focus,.btn-danger.disabled:active,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled],.btn-danger[disabled].active,.btn-danger[disabled].focus,.btn-danger[disabled]:active,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger,fieldset[disabled] .btn-danger.active,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:active,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{font-weight:400;color:#337ab7;border-radius:0}.btn-link,.btn-link.active,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:active,.btn-link:focus,.btn-link:hover{border-color:transparent}.btn-link:focus,.btn-link:hover{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:focus,.btn-link[disabled]:hover,fieldset[disabled] .btn-link:focus,fieldset[disabled] .btn-link:hover{color:#777;text-decoration:none}.btn-group-lg>.btn,.btn-lg{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-group-sm>.btn,.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-xs>.btn,.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease;-webkit-transition-duration:.35s;-o-transition-duration:.35s;transition-duration:.35s;-webkit-transition-property:height,visibility;-o-transition-property:height,visibility;transition-property:height,visibility}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid\9;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown,.dropup{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;text-align:left;list-style:none;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{color:#262626;text-decoration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{color:#fff;text-decoration:none;background-color:#337ab7;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{color:#777}.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{right:0;left:auto}.dropdown-menu-left{right:auto;left:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{content:"";border-top:0;border-bottom:4px dashed;border-bottom:4px solid\9}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}.navbar-right .dropdown-menu-left{right:auto;left:0}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;float:left}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-left-radius:0;border-top-right-radius:0;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-top-right-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle=buttons]>.btn input[type=checkbox],[data-toggle=buttons]>.btn input[type=radio],[data-toggle=buttons]>.btn-group>.btn input[type=checkbox],[data-toggle=buttons]>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-right:0;padding-left:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn,textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn,textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn{height:auto}.input-group .form-control,.input-group-addon,.input-group-btn{display:table-cell}.input-group .form-control:not(:first-child):not(:last-child),.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=checkbox],.input-group-addon input[type=radio]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn-group:not(:last-child)>.btn,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:first-child>.btn-group:not(:first-child)>.btn,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:active,.input-group-btn>.btn:focus,.input-group-btn>.btn:hover{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{z-index:2;margin-left:-1px}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:focus,.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:focus,.nav>li.disabled>a:hover{color:#777;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:focus,.nav .open>a:hover{background-color:#eee;border-color:#337ab7}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:focus,.nav-tabs>li.active>a:hover{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:focus,.nav-pills>li.active>a:hover{color:#fff;background-color:#337ab7}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{padding-right:15px;padding-left:15px;overflow-x:visible;-webkit-overflow-scrolling:touch;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1)}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse{padding-right:0;padding-left:0}}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:200px}}.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-bottom,.navbar-fixed-top{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-bottom,.navbar-fixed-top{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;height:50px;padding:15px 15px;font-size:18px;line-height:20px}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-top:8px;margin-right:15px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu .dropdown-header,.navbar-nav .open .dropdown-menu>li>a{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:focus,.navbar-nav .open .dropdown-menu>li>a:hover{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{padding:10px 15px;margin-top:8px;margin-right:-15px;margin-bottom:8px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1)}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .form-control,.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .checkbox,.navbar-form .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .checkbox label,.navbar-form .radio label{padding-left:0}.navbar-form .checkbox input[type=checkbox],.navbar-form .radio input[type=radio]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-left-radius:0;border-top-right-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-right:15px;margin-left:15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:focus,.navbar-default .navbar-brand:hover{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:focus,.navbar-default .navbar-nav>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:focus,.navbar-default .navbar-nav>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:focus,.navbar-default .navbar-nav>.disabled>a:hover{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:focus,.navbar-default .navbar-toggle:hover{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:focus,.navbar-default .navbar-nav>.open>a:hover{color:#555;background-color:#e7e7e7}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:focus,.navbar-default .btn-link:hover{color:#333}.navbar-default .btn-link[disabled]:focus,.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:focus,fieldset[disabled] .navbar-default .btn-link:hover{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:focus,.navbar-inverse .navbar-brand:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:focus,.navbar-inverse .navbar-nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:focus,.navbar-inverse .navbar-nav>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:focus,.navbar-inverse .navbar-nav>.disabled>a:hover{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:focus,.navbar-inverse .navbar-toggle:hover{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:focus,.navbar-inverse .navbar-nav>.open>a:hover{color:#fff;background-color:#080808}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:focus,.navbar-inverse .btn-link:hover{color:#fff}.navbar-inverse .btn-link[disabled]:focus,.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:focus,fieldset[disabled] .navbar-inverse .btn-link:hover{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.42857143;color:#337ab7;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:4px;border-bottom-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{z-index:3;color:#23527c;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:2;color:#fff;cursor:default;background-color:#337ab7;border-color:#337ab7}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#777;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:6px;border-bottom-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:3px;border-bottom-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:focus,.pager li>a:hover{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:focus,.pager .disabled>a:hover,.pager .disabled>span{color:#777;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:focus,a.label:hover{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:focus,.label-default[href]:hover{background-color:#5e5e5e}.label-primary{background-color:#337ab7}.label-primary[href]:focus,.label-primary[href]:hover{background-color:#286090}.label-success{background-color:#5cb85c}.label-success[href]:focus,.label-success[href]:hover{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:focus,.label-info[href]:hover{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:focus,.label-warning[href]:hover{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:focus,.label-danger[href]:hover{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:middle;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-group-xs>.btn .badge,.btn-xs .badge{top:0;padding:1px 5px}a.badge:focus,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding-top:30px;padding-bottom:30px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron .h1,.jumbotron h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron,.container-fluid .jumbotron{padding-right:60px;padding-left:60px}.jumbotron .h1,.jumbotron h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail a>img,.thumbnail>img{margin-right:auto;margin-left:auto}a.thumbnail.active,a.thumbnail:focus,a.thumbnail:hover{border-color:#337ab7}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#337ab7;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-bar-striped,.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress-bar.active,.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{overflow:hidden;zoom:1}.media-body{width:10000px}.media-object{display:block}.media-object.img-thumbnail{max-width:none}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-body,.media-left,.media-right{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}a.list-group-item,button.list-group-item{color:#555}a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333}a.list-group-item:focus,a.list-group-item:hover,button.list-group-item:focus,button.list-group-item:hover{color:#555;text-decoration:none;background-color:#f5f5f5}button.list-group-item{width:100%;text-align:left}.list-group-item.disabled,.list-group-item.disabled:focus,.list-group-item.disabled:hover{color:#777;cursor:not-allowed;background-color:#eee}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7}.list-group-item.active .list-group-item-heading,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:focus .list-group-item-text,.list-group-item.active:hover .list-group-item-text{color:#c7ddef}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success,button.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:focus,a.list-group-item-success:hover,button.list-group-item-success:focus,button.list-group-item-success:hover{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:focus,a.list-group-item-success.active:hover,button.list-group-item-success.active,button.list-group-item-success.active:focus,button.list-group-item-success.active:hover{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info,button.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:focus,a.list-group-item-info:hover,button.list-group-item-info:focus,button.list-group-item-info:hover{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:focus,a.list-group-item-info.active:hover,button.list-group-item-info.active,button.list-group-item-info.active:focus,button.list-group-item-info.active:hover{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning,button.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:focus,a.list-group-item-warning:hover,button.list-group-item-warning:focus,button.list-group-item-warning:hover{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:focus,a.list-group-item-warning.active:hover,button.list-group-item-warning.active,button.list-group-item-warning.active:focus,button.list-group-item-warning.active:hover{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger,button.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:focus,a.list-group-item-danger:hover,button.list-group-item-danger:focus,button.list-group-item-danger:hover{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:focus,a.list-group-item-danger.active:hover,button.list-group-item-danger.active,button.list-group-item-danger.active:focus,button.list-group-item-danger.active:hover{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>.small,.panel-title>.small>a,.panel-title>a,.panel-title>small,.panel-title>small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-left-radius:3px;border-top-right-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-left-radius:0;border-top-right-radius:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.panel-collapse>.table,.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.panel-collapse>.table caption,.panel>.table caption,.panel>.table-responsive>.table caption{padding-right:15px;padding-left:15px}.panel>.table-responsive:first-child>.table:first-child,.panel>.table:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table:first-child>thead:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table-responsive:last-child>.table:last-child,.panel>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child td,.panel>.table>tbody:first-child>tr:first-child th{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{margin-bottom:0;border:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.list-group,.panel-group .panel-heading+.panel-collapse>.panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#337ab7}.panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7}.panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2}.close:focus,.close:hover{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}button.close{-webkit-appearance:none;padding:0;cursor:pointer;background:0 0;border:0}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out;-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);-o-transform:translate(0,-25%);transform:translate(0,-25%)}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5)}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{filter:alpha(opacity=0);opacity:0}.modal-backdrop.in{filter:alpha(opacity=50);opacity:.5}.modal-header{min-height:16.43px;padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:12px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;filter:alpha(opacity=0);opacity:0;line-break:auto}.tooltip.in{filter:alpha(opacity=90);opacity:.9}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{right:5px;bottom:0;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);line-break:auto}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{content:"";border-width:10px}.popover.top>.arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,.25);border-bottom-width:0}.popover.top>.arrow:after{bottom:1px;margin-left:-10px;content:" ";border-top-color:#fff;border-bottom-width:0}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,.25);border-left-width:0}.popover.right>.arrow:after{bottom:-10px;left:1px;content:" ";border-right-color:#fff;border-left-width:0}.popover.bottom>.arrow{top:-11px;left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25)}.popover.bottom>.arrow:after{top:1px;margin-left:-10px;content:" ";border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left>.arrow:after{right:1px;bottom:-10px;content:" ";border-right-width:0;border-left-color:#fff}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>a>img,.carousel-inner>.item>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-inner>.item.active.right,.carousel-inner>.item.next{left:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}.carousel-inner>.item.active.left,.carousel-inner>.item.prev{left:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.carousel-inner>.item.active,.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right{left:0;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6);filter:alpha(opacity=50);opacity:.5}.carousel-control.left{background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,.0001)));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);background-repeat:repeat-x}.carousel-control.right{right:0;left:auto;background-image:-webkit-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.0001)),to(rgba(0,0,0,.5)));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);background-repeat:repeat-x}.carousel-control:focus,.carousel-control:hover{color:#fff;text-decoration:none;filter:alpha(opacity=90);outline:0;opacity:.9}.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{position:absolute;top:50%;z-index:5;display:inline-block;margin-top:-10px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{left:50%;margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{right:50%;margin-right:-10px}.carousel-control .icon-next,.carousel-control .icon-prev{width:20px;height:20px;font-family:serif;line-height:1}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000\9;background-color:rgba(0,0,0,0);border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{width:30px;height:30px;margin-top:-15px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-15px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-15px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.btn-group-vertical>.btn-group:after,.btn-group-vertical>.btn-group:before,.btn-toolbar:after,.btn-toolbar:before,.clearfix:after,.clearfix:before,.container-fluid:after,.container-fluid:before,.container:after,.container:before,.dl-horizontal dd:after,.dl-horizontal dd:before,.form-horizontal .form-group:after,.form-horizontal .form-group:before,.modal-footer:after,.modal-footer:before,.nav:after,.nav:before,.navbar-collapse:after,.navbar-collapse:before,.navbar-header:after,.navbar-header:before,.navbar:after,.navbar:before,.pager:after,.pager:before,.panel-body:after,.panel-body:before,.row:after,.row:before{display:table;content:" "}.btn-group-vertical>.btn-group:after,.btn-toolbar:after,.clearfix:after,.container-fluid:after,.container:after,.dl-horizontal dd:after,.form-horizontal .form-group:after,.modal-footer:after,.nav:after,.navbar-collapse:after,.navbar-header:after,.navbar:after,.pager:after,.panel-body:after,.row:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-lg,.visible-md,.visible-sm,.visible-xs{display:none!important}.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table!important}tr.visible-xs{display:table-row!important}td.visible-xs,th.visible-xs{display:table-cell!important}}@media (max-width:767px){.visible-xs-block{display:block!important}}@media (max-width:767px){.visible-xs-inline{display:inline!important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table!important}tr.visible-sm{display:table-row!important}td.visible-sm,th.visible-sm{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table!important}tr.visible-md{display:table-row!important}td.visible-md,th.visible-md{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table!important}tr.visible-lg{display:table-row!important}td.visible-lg,th.visible-lg{display:table-cell!important}}@media (min-width:1200px){.visible-lg-block{display:block!important}}@media (min-width:1200px){.visible-lg-inline{display:inline!important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table!important}tr.visible-print{display:table-row!important}td.visible-print,th.visible-print{display:table-cell!important}}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}}
/* Space out content a bit */
body, form, ul, table {
margin-top: 20px;
margin-bottom: 20px;
}
/* Phoenix flash messages */
.alert:empty { display: none; }
/* Phoenix inline forms in links and buttons */
form.link, form.button {
display: inline;
}
/* Custom page header */
.header {
border-bottom: 1px solid #e5e5e5;
}
.logo {
width: 519px;
height: 71px;
display: inline-block;
margin-bottom: 1em;
background-image: url("/images/phoenix.png");
background-size: 519px 71px;
}
/* Everything but the jumbotron gets side spacing for mobile first views */
.header,
.marketing {
padding-right: 15px;
padding-left: 15px;
}
/* Customize container */
@media (min-width: 768px) {
.container {
max-width: 730px;
}
}
.container-narrow > hr {
margin: 30px 0;
}
/* Main marketing message */
.jumbotron {
text-align: center;
border-bottom: 1px solid #e5e5e5;
}
/* Supporting marketing content */
.marketing {
margin: 35px 0;
}
/* Responsive: Portrait tablets and up */
@media screen and (min-width: 768px) {
/* Remove the padding we set earlier */
.header,
.marketing {
padding-right: 0;
padding-left: 0;
}
/* Space out the masthead */
.header {
margin-bottom: 30px;
}
/* Remove the bottom border on the jumbotron for visual effect */
.jumbotron {
border-bottom: 0;
}
}
================================================
FILE: example_app/web/static/js/app.js
================================================
// Brunch automatically concatenates all files in your
// watched paths. Those paths can be configured at
// config.paths.watched in "brunch-config.js".
//
// However, those files will only be executed if
// explicitly imported. The only exception are files
// in vendor, which are never wrapped in imports and
// therefore are always executed.
// Import dependencies
//
// If you no longer want to use a dependency, remember
// to also remove its path from "config.paths.watched".
import "phoenix_html"
// Import local files
//
// Local files can be imported directly using relative
// paths "./socket" or full ones "web/static/js/socket".
// import socket from "./socket"
================================================
FILE: example_app/web/static/js/socket.js
================================================
// NOTE: The contents of this file will only be executed if
// you uncomment its entry in "web/static/js/app.js".
// To use Phoenix channels, the first step is to import Socket
// and connect at the socket path in "lib/my_app/endpoint.ex":
import {Socket} from "phoenix"
let socket = new Socket("/socket", {params: {token: window.userToken}})
// When you connect, you'll often need to authenticate the client.
// For example, imagine you have an authentication plug, `MyAuth`,
// which authenticates the session and assigns a `:current_user`.
// If the current user exists you can assign the user's token in
// the connection for use in the layout.
//
// In your "web/router.ex":
//
// pipeline :browser do
// ...
// plug MyAuth
// plug :put_user_token
// end
//
// defp put_user_token(conn, _) do
// if current_user = conn.assigns[:current_user] do
// token = Phoenix.Token.sign(conn, "user socket", current_user.id)
// assign(conn, :user_token, token)
// else
// conn
// end
// end
//
// Now you need to pass this token to JavaScript. You can do so
// inside a script tag in "web/templates/layout/app.html.eex":
//
// <script>window.userToken = "<%= assigns[:user_token] %>";</script>
//
// You will need to verify the user token in the "connect/2" function
// in "web/channels/user_socket.ex":
//
// def connect(%{"token" => token}, socket) do
// # max_age: 1209600 is equivalent to two weeks in seconds
// case Phoenix.Token.verify(socket, "user socket", token, max_age: 1209600) do
// {:ok, user_id} ->
// {:ok, assign(socket, :user, user_id)}
// {:error, reason} ->
// :error
// end
// end
//
// Finally, pass the token on connect as below. Or remove it
// from connect if you don't care about authentication.
socket.connect()
// Now that you are connected, you can join channels with a topic:
let channel = socket.channel("topic:subtopic", {})
channel.join()
.receive("ok", resp => { console.log("Joined successfully", resp) })
.receive("error", resp => { console.log("Unable to join", resp) })
export default socket
================================================
FILE: example_app/web/templates/layout/app.html.eex
================================================
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<title>Hello ExampleApp!</title>
<link rel="stylesheet" href="<%= static_path(@conn, "/css/app.css") %>">
</head>
<body>
<div class="container">
<header class="header">
<nav role="navigation">
<ul class="nav nav-pills pull-right">
<li><a href="http://www.phoenixframework.org/docs">Get Started</a></li>
</ul>
</nav>
<span class="logo"></span>
</header>
<ul class="">
<%= if @current_user do %>
<li><%= @current_user.email %></li>
<li><%= link "Log out", to: session_path(@conn, :delete) %>
<% else %>
<li><%= link "Login", to: session_path(@conn, :new) %></li>
<li><%= link "Register", to: registration_path(@conn, :new) %></li>
<% end %>
</ul>
<p class="alert alert-info" role="alert"><%= get_flash(@conn, :info) %></p>
<p class="alert alert-danger" role="alert"><%= get_flash(@conn, :error) %></p>
<main role="main">
<%= render @view_module, @view_template, assigns %>
</main>
</div> <!-- /container -->
<script src="<%= static_path(@conn, "/js/app.js") %>"></script>
</body>
</html>
================================================
FILE: example_app/web/templates/page/index.html.eex
================================================
<div class="jumbotron">
<h2><%= gettext "Welcome to %{name}", name: "Phoenix!" %></h2>
<p class="lead">A productive web framework that<br />does not compromise speed and maintainability.</p>
</div>
<div class="row marketing">
<div class="col-lg-6">
<h4>Resources</h4>
<ul>
<li>
<a href="http://phoenixframework.org/docs/overview">Guides</a>
</li>
<li>
<a href="http://hexdocs.pm/phoenix">Docs</a>
</li>
<li>
<a href="https://github.com/phoenixframework/phoenix">Source</a>
</li>
</ul>
</div>
<div class="col-lg-6">
<h4>Help</h4>
<ul>
<li>
<a href="http://groups.google.com/group/phoenix-talk">Mailing list</a>
</li>
<li>
<a href="http://webchat.freenode.net/?channels=elixir-lang">#elixir-lang on freenode IRC</a>
</li>
<li>
<a href="https://twitter.com/elixirphoenix">@elixirphoenix</a>
</li>
</ul>
</div>
</div>
================================================
FILE: example_app/web/templates/password/forget_password.html.eex
================================================
<h3>Request new password</h3>
<%= form_for @conn, password_path(@conn, :reset_password), [as: :user], fn f -> %>
<div class="form-group">
<%= text_input f, :email, placeholder: "email", class: "form-control" %>
</div>
<%= submit "Reset Password", class: "btn btn-primary" %>
<% end %>
================================================
FILE: example_app/web/templates/registration/new.html.eex
================================================
<h1>Register</h1>
<%= form_for @changeset, registration_path(@conn, :create), fn f -> %>
<%= if f.errors != [] do %>
<div class="alert alert-danger">
<p>Oops, something went wrong!<br> Please check the errors below:</p>
<ul>
<%= for {attr, message} <- f.errors do %>
<li><%= humanize(attr) %> <%= translate_error(message) %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="form-group">
<%= text_input f, :email, placeholder: "email", class: "form-control" %>
</div>
<div class="form-group">
<%= password_input f, :password, placeholder: "Password", class: "form-control" %>
</div>
<%= submit "Register", class: "btn btn-primary" %>
<% end %>
================================================
FILE: example_app/web/templates/session/new.html.eex
================================================
<h1>Login</h1>
<%= form_for @conn, session_path(@conn, :create), [as: :session], fn f -> %>
<div class="form-group">
<%= text_input f, :email, placeholder: "Email", class: "form-control" %>
</div>
<div class="form-group">
<%= password_input f, :password, placeholder: "Password", class: "form-control" %>
</div>
<%= submit "Log in", class: "btn btn-primary" %>
<% end %>
================================================
FILE: example_app/web/views/error_helpers.ex
================================================
defmodule ExampleApp.ErrorHelpers do
@moduledoc """
Conveniences for translating and building error messages.
"""
use Phoenix.HTML
@doc """
Generates tag for inlined form input errors.
"""
def error_tag(form, field) do
if error = form.errors[field] do
content_tag :span, translate_error(error), class: "help-block"
end
end
@doc """
Translates an error message using gettext.
"""
def translate_error({msg, opts}) do
# Because error messages were defined within Ecto, we must
# call the Gettext module passing our Gettext backend. We
# also use the "errors" domain as translations are placed
# in the errors.po file. On your own code and templates,
# this could be written simply as:
#
# dngettext "errors", "1 file", "%{count} files", count
#
Gettext.dngettext(ExampleApp.Gettext, "errors", msg, msg, opts[:count], opts)
end
def translate_error(msg) do
Gettext.dgettext(ExampleApp.Gettext, "errors", msg)
end
end
================================================
FILE: example_app/web/views/error_view.ex
================================================
defmodule ExampleApp.ErrorView do
use ExampleApp.Web, :view
def render("404.html", _assigns) do
"Page not found"
end
def render("500.html", _assigns) do
"Server internal error"
end
# In case no render clause matches or no
# template is found, let's render it as 500
def template_not_found(_template, assigns) do
render "500.html", assigns
end
end
================================================
FILE: example_app/web/views/layout_view.ex
================================================
defmodule ExampleApp.LayoutView do
use ExampleApp.Web, :view
end
================================================
FILE: example_app/web/views/page_view.ex
================================================
defmodule ExampleApp.PageView do
use ExampleApp.Web, :view
end
================================================
FILE: example_app/web/views/password_view.ex
================================================
defmodule ExampleApp.PasswordView do
use ExampleApp.Web, :view
end
================================================
FILE: example_app/web/views/registration_view.ex
================================================
defmodule ExampleApp.RegistrationView do
use ExampleApp.Web, :view
end
================================================
FILE: example_app/web/views/session_view.ex
================================================
defmodule ExampleApp.SessionView do
use ExampleApp.Web, :view
end
================================================
FILE: example_app/web/web.ex
================================================
defmodule ExampleApp.Web do
@moduledoc """
A module that keeps using definitions for controllers,
views and so on.
This can be used in your application as:
use ExampleApp.Web, :controller
use ExampleApp.Web, :view
The definitions below will be executed for every view,
controller, etc, so keep them short and clean, focused
on imports, uses and aliases.
Do NOT define functions inside the quoted expressions
below.
"""
def model do
quote do
use Ecto.Schema
import Ecto
import Ecto.Changeset
import Ecto.Query, only: [from: 1, from: 2]
end
end
def controller do
quote do
use Phoenix.Controller
alias ExampleApp.Repo
import Ecto
import Ecto.Query, only: [from: 1, from: 2]
import ExampleApp.Router.Helpers
import ExampleApp.Gettext
end
end
def view do
quote do
use Phoenix.View, root: "web/templates"
# Import convenience functions from controllers
import Phoenix.Controller, only: [get_csrf_token: 0, get_flash: 2, view_module: 1]
# Use all HTML functionality (forms, tags, etc)
use Phoenix.HTML
import ExampleApp.Router.Helpers
import ExampleApp.ErrorHelpers
import ExampleApp.Gettext
end
end
def router do
quote do
use Phoenix.Router
end
end
def channel do
quote do
use Phoenix.Channel
alias ExampleApp.Repo
import Ecto
import Ecto.Query, only: [from: 1, from: 2]
import ExampleApp.Gettext
end
end
@doc """
When used, dispatch to the appropriate controller/view/etc.
"""
defmacro __using__(which) when is_atom(which) do
apply(__MODULE__, which, [])
end
end
================================================
FILE: lib/mix/tasks/install.ex
================================================
defmodule Mix.Tasks.Passport.Install do
use Mix.Task
@shortdoc "Generates controller, model and views for authentication resource"
@moduledoc """
Generates a Phoenix resource for user authentication.
mix passport.install
or
mix passport.install Admin admins
The first argument is the module name for the user and the second argument is the plural form of the module name. If omitted, it uses default module name as User and its plural form users.
The generated resource will contain:
* a model in web/models
* a controller, a view, and templates for User registration
* a controller, a view, and templates for Session management
* a controller, a view, and templates for Password reset
* a migration file for the repository
"""
def run(args) do
{_, parsed, _} = OptionParser.parse(args)
[singular, plural] = validate_args!(parsed)
binding = Mix.Phoenix.inflect(singular)
path = binding[:path]
migration = String.replace(path, "/", "_")
binding = binding ++ [plural: plural,
template_singular: String.replace(binding[:singular], "_", " "),
template_plural: String.replace(plural, "_", " ")]
IO.puts inspect binding
Mix.Phoenix.check_module_name_availability!(binding[:module] <> "Controller")
Mix.Phoenix.check_module_name_availability!(binding[:module] <> "View")
files =
[
{:eex, "model.ex", "web/models/#{path}.ex"},
{:eex, "migration.exs", "priv/repo/migrations/#{timestamp()}_create_#{migration}.exs"},
{:eex, "session_view.ex", "web/views/session_view.ex"},
{:eex, "registration_view.ex", "web/views/registration_view.ex"},
{:eex, "password_view.ex", "web/views/password_view.ex"},
{:eex, "registration_controller.ex", "web/controllers/registration_controller.ex"},
{:eex, "session_controller.ex", "web/controllers/session_controller.ex"},
{:eex, "password_controller.ex", "web/controllers/password_controller.ex"},
{:eex, "session_new.html.eex", "web/templates/session/new.html.eex"},
{:eex, "registration_new.html.eex", "web/templates/registration/new.html.eex"},
{:eex, "password_new.html.eex", "web/templates/password/new.html.eex"},
]
Mix.Phoenix.copy_from paths(), "priv/templates/passport.install", "", binding, files
instructions = """
Use Passport in your web/router.ex
use Passport
add the plug `:current_user` in your browser pipeline
pipeline :browser do
...
plug :current_user
end
Add the following routes to your browser scope in web/router.ex:
get "/login", SessionController, :new
post "/session", SessionController, :create
get "/logout", SessionController, :delete
get "/join", RegistrationController, :new
post "/register", RegistrationController, :create
get "/passwords/new", PasswordController, :new
post "/passwords", PasswordController, :reset
scope "/" do
pipe_through :authenticate
# routes that require login go here
end
Add Passport configuration in your config.exs like below:
config :passport,
resource: #{binding[:module]},
repo: #{binding[:base]}.Repo
Optionally, in your navigation you may to include this:
<ul class="">
<%= if @current_user do %>
<li><%= @current_user.email %></li>
<li><%= link "Log out", to: session_path(@conn, :delete) %></li>
<% else %>
<li><%= link "Login", to: session_path(@conn, :new) %></li>
<li><%= link "Register", to: registration_path(@conn, :new) %></li>
<% end %>
</ul>
Finally, update your repository:
$ mix ecto.migrate
"""
Mix.shell.info instructions
end
defp validate_args!([_singular, plural] = args) do
cond do
plural != Phoenix.Naming.underscore(plural) ->
Mix.raise "expected the second argument, #{inspect plural}, to be all lowercase using snake_case convention"
true ->
args
end
end
defp validate_args!([]) do
["User", "users"]
end
defp validate_args!(_) do
raise_with_help()
end
defp raise_with_help do
Mix.raise """
mix passport.install expects both singular and plural names
mix passport.install User users
or just type without any arguments to create a User resource
mix passport.install
"""
end
defp timestamp do
{{y, m, d}, {hh, mm, ss}} = :calendar.universal_time()
"#{y}#{pad(m)}#{pad(d)}#{pad(hh)}#{pad(mm)}#{pad(ss)}"
end
defp pad(i) when i < 10, do: << ?0, ?0 + i >>
defp pad(i), do: to_string(i)
defp paths do
[".", :passport]
end
end
================================================
FILE: lib/mix/tasks/passport.setup.ex
================================================
defmodule Mix.Tasks.Passport.Setup do
use Mix.Task
alias Mix.Phoenix.Context
@shortdoc "Generates controller, model and views for authentication resource"
@moduledoc """
"""
def run(_) do
paths = [".", :passport]
with :ok <- generate_account(paths),
:ok <- generate_auth(paths),
:ok <- generate_web(paths),
:ok <- generate_config do
print_shell_instructions
end
end
defp generate_account(paths) do
args = ["Account", "User", "users"]
{context, schema} = Mix.Tasks.Phx.Gen.Html.build(args)
binding = [context: context, schema: schema]
Mix.Phoenix.copy_from paths, "priv/templates/account", "", binding, [
{:eex, "user_schema.ex", context.schema.file},
{:eex, "user_migration.exs", "priv/repo/migrations/#{timestamp()}_create_passport_user_table.exs"},
{:eex, "account_context.ex", context.file},
]
:ok
end
defp generate_auth(paths) do
args = ["Auth", "Password", "passwords"]
{context, schema} = Mix.Tasks.Phx.Gen.Html.build(args)
binding = [context: context, schema: schema]
Mix.Phoenix.copy_from paths, "priv/templates/auth", "", binding, [
{:eex, "password_schema.ex", context.schema.file},
{:eex, "password_migration.exs", "priv/repo/migrations/#{timestamp()}_create_passport_password_table.exs"},
{:eex, "auth_context.ex", context.file},
]
:ok
end
defp generate_web(paths) do
web_prefix = Mix.Phoenix.web_prefix()
binding = [
web_module: Mix.Phoenix.base <> ".Web",
account_module: Mix.Phoenix.base <> ".Account",
auth_module: Mix.Phoenix.base <> ".Auth"
]
Mix.Phoenix.copy_from paths, "priv/templates/web", "", binding, [
{:eex, "session_controller.ex", Path.join(web_prefix, "controllers/session_controller.ex")},
{:eex, "session_view.ex", Path.join(web_prefix, "views/session_view.ex")},
{:eex, "login.html.eex", Path.join(web_prefix, "templates/session/new.html.eex")},
{:eex, "registration_controller.ex", Path.join(web_prefix, "controllers/registration_controller.ex")},
{:eex, "registration_view.ex", Path.join(web_prefix, "views/registration_view.ex")},
{:eex, "register.html.eex", Path.join(web_prefix, "templates/registration/new.html.eex")}
]
:ok
end
defp generate_config() do
{:ok, file} = File.open("./config/config.exs", [:append, :utf8])
passport_config = """
config :passport,
repo: #{Mix.Phoenix.base() <> ".Repo"},
account_module: #{Mix.Phoenix.base() <> ".Account"},
account_user: #{Mix.Phoenix.base() <> ".Account.User"},
auth_keys: ["email"],
auth_module: #{Mix.Phoenix.base() <> ".Auth"},
enabled_auths: [Passport.Password],
auth_password: #{Mix.Phoenix.base() <> ".Auth.Password"}
"""
Mix.shell.info [:green, "* updating config/config.exs"]
IO.write(file, passport_config)
:ok = File.close(file)
end
defp copy_new_files(_context, paths, binding) do
web_prefix = Mix.Phoenix.web_prefix()
[context: context, user_schema: user_schema, password_schema: password_schema] = binding
Mix.Phoenix.copy_from paths, "priv/templates/passport.install", "", binding, [
{:eex, "session_controller.ex", Path.join(web_prefix, "controllers/session_controller.ex")},
{:eex, "registration_controller.ex", Path.join(web_prefix, "controllers/registration_controller.ex")},
{:eex, "login.html.eex", Path.join(web_prefix, "templates/session/new.html.eex")},
{:eex, "register.html.eex", Path.join(web_prefix, "templates/registration/new.html.eex")},
{:eex, "session_view.ex", Path.join(web_prefix, "views/session_view.ex")},
{:eex, "registration_view.ex", Path.join(web_prefix, "views/registration_view.ex")},
{:eex, "user_schema.ex", user_schema.file},
{:eex, "password_schema.ex", password_schema.file},
{:eex, "registration_password_schema.ex", Path.join(context.dir, "registration_password.ex")},
{:eex, "user_migration.exs", "priv/repo/migrations/#{timestamp()}_create_passport_user_table.exs"},
{:eex, "password_migration.exs", "priv/repo/migrations/#{timestamp()}_create_passport_password_table.exs"},
{:eex, "context.ex", context.file},
]
context
end
defp print_shell_instructions() do
base = Mix.Phoenix.base()
Mix.shell.info """
`config/config.exs` file has been appended with Passport config as below:
Just add the following changes to your router.ex
1. Modify your "/" scope to include the following paths.
scope "/", #{base}.Web do
...
get "/login", SessionController, :new
post "/session", SessionController, :create
get "/logout", SessionController, :delete
get "/register", RegistrationController, :new
post "/register", RegistrationController, :create
end
2. Add the following plug to your pipeline
```
import #{base}.Auth, only: [load_current_user: 2]
pipeline :browser do
...
plug :load_current_user
end
3. Add the following code to your layout `app.html.eex`
<%= if user = #{base}.Auth.current_user(@conn) do %>
<%= "Logged in as \#{user.email}" %>
<a href="/logout">Logout</a>
<% else %>
<a href="/register">Register</a>
<a href="/login">Login</a>
<% end %>
"""
end
defp timestamp do
:timer.sleep(1000) # hack to avoid two consecutive migrations from having having the same timestamp.
{{y, m, d}, {hh, mm, ss}} = :calendar.universal_time()
"#{y}#{pad(m)}#{pad(d)}#{pad(hh)}#{pad(mm)}#{pad(ss)}"
end
defp pad(i) when i < 10, do: << ?0, ?0 + i >>
defp pad(i), do: to_string(i)
end
================================================
FILE: lib/passport/account.ex
================================================
defmodule Passport.Account do
@callback get_user(String.t) :: map
# defmacro __using__(opts) do
# quote do
# @behaviour Passport.Account
#
# end
# end
end
================================================
FILE: lib/passport/auth.ex
================================================
defmodule Passport.Auth do
import Plug.Conn
defmacro __using__(_opts) do
quote do
import Plug.Conn
import Phoenix.Controller, only: [redirect: 2, put_flash: 3]
unquote(define_enabled_type_defs())
unquote(plugs())
end
end
defp plugs() do
quote do
@doc """
Plug that validates the details and signs in the account.
"""
def login(type, conn, params) do
with account when account != nil <- Passport.Auth.get_account(params),
true <- valid_credential?(type, account, Map.get(params, "password"))
do
{:ok, Passport.Auth.do_login(conn, account)}
else
_ ->
{:error, conn}
end
end
@doc """
Plug that signs out the account.
"""
def logout(conn, params \\ []) do
conn
|> configure_session(drop: true)
end
@doc """
Load the current user into conn
"""
def load_current_user(conn, opts) do
with user_id when user_id != nil <- get_session(conn, :user_id),
user <- Passport.Config.account_module.get_user(user_id) do
conn
|> assign(:current_user, user)
else
_ ->
conn
end
end
@doc """
Helper function to get current user from conn
"""
def current_user(conn, _opts \\ []) do
Map.get(conn.assigns, :current_user)
end
def require_login(conn, opts) do
if (user = current_user(conn)) do
conn
else
conn
|> put_session(:last_visit_path, conn.request_path)
|> put_flash(:info, opts[:message])
|> redirect(to: opts[:redirect_path])
end
end
def redirect_back_or_to(conn, path) do
path = case get_session(conn, :last_visit_path) do
nil -> path
last_visit_path -> last_visit_path
end
conn
|> delete_session(:last_visit_path)
|> redirect(to: path)
end
end
end
def do_login(conn, user) do
conn
|> fetch_session
|> put_session(:user_id, user.id)
|> assign(:current_user, user)
|> configure_session(renew: true)
end
defp define_enabled_type_defs() do
enabled_auths = Passport.Config.enabled_auths
|> Enum.map(fn(module) ->
auth_type = Phoenix.Naming.resource_name(module) |> String.to_atom
{auth_type, module}
end)
quote bind_quoted: [enabled_auths: enabled_auths] do
Enum.each enabled_auths, fn ({type, module}) ->
def valid_credential?(unquote(type), account, password) do
apply(unquote(module), :valid_credential?, [account, password])
end
end
end
end
def get_account(params) do
query_clause = Map.take(params, Passport.Config.auth_keys)
|> Enum.map(fn({k,v}) ->
{String.to_atom(k), v}
end)
Passport.Config.account_user
|> Passport.Config.repo.get_by(query_clause)
end
end
================================================
FILE: lib/passport/auth_type/auth_type.ex
================================================
defmodule Passport.AuthType do
@callback valid_credential?(map, String.t) :: map
@callback save_credential(map) :: atom
@callback update_credential(integer, map) :: atom
@callback delete_credential(integer) :: atom
end
================================================
FILE: lib/passport/auth_type/password/crypto.ex
================================================
defmodule Passport.Password.Crypto do
import Comeonin.Bcrypt, only: [checkpw: 2, hashpwsalt: 1]
def hash(password) do
hashpwsalt(password)
end
def valid_password?(given_password, password_hash) do
checkpw(given_password, password_hash)
end
end
================================================
FILE: lib/passport/auth_type/password/password.ex
================================================
defmodule Passport.Password do
@behaviour Passport.AuthType
alias Passport.Config
import Passport.Password.Crypto, only: [valid_password?: 2]
@doc """
Checks if the given password is valid for the account.
"""
def valid_credential?(account, password) do
with active_password when active_password != nil <- get_active_password(account),
true <- valid_password?(password, active_password.password_hash)
do
true
else
error ->
false
end
end
@doc """
Save a new password credential
"""
def save_credential(credential) do
# %Article{}
# |> article_changeset(attrs)
# |> Repo.insert()
Config.repo.insert(credential)
end
@doc """
Update an existing password credential
"""
def update_credential(credential) do
Config.repo.insert(credential)
end
@doc """
Delete a password credential
"""
def delete_credential(credential) do
Config.repo.insert(credential)
end
@doc """
Get the active password for the given id
"""
defp get_active_password(%{id: id}) do
Config.auth_password
|> Config.repo.get_by(user_id: id)
end
defp get_active_password(_) do
{:error, "Account must be map with :id key"}
end
end
================================================
FILE: lib/passport/config.ex
================================================
defmodule Passport.Config do
@default_config [
repo: "nil",
account_module: "nil",
account_user: "nil",
auth_keys: ["email"],
enabled_auths: [],
auth_module: nil,
auth_password: nil,
]
def default_config do
@default_config
end
@default_config
|> Keyword.keys()
|> Enum.each(fn key ->
def unquote(key)() do
Application.get_env(:passport, unquote(key))
end
end)
end
================================================
FILE: lib/passport/plug.ex
================================================
defmodule Passport.Plug do
import Plug.Conn
import Phoenix.Controller, only: [redirect: 2, put_flash: 3]
def current_user(conn, _) do
user_id = get_session(conn, :user_id)
user = user_id && fetch_user_by_id(user_id)
assign(conn, :current_user, user)
end
def authenticate(conn, _) do
authenticate_env(:prod, conn)
end
defp authenticate_env(:test, conn) do
case conn.params["as"] do
nil ->
conn
id ->
user = fetch_user_by_id(id)
conn
|> assign(:current_user, user)
|> put_session(:user_id, user.id)
|> configure_session(renew: true)
end
end
defp authenticate_env(_, conn) do
case conn.assigns[:current_user] do
nil ->
conn
|> put_flash(:info, "You must be signed in")
|> redirect(to: "/login")
|> configure_session(renew: true)
|> halt
_ ->
conn
end
end
defp fetch_user_by_id(id) do
Passport.Config.repo.get(Passport.Config.resource, id)
end
end
================================================
FILE: lib/passport/router.ex
================================================
================================================
FILE: lib/passport/session.ex
================================================
defmodule Passport.Session do
import Plug.Conn
import Comeonin.Bcrypt, only: [checkpw: 2]
def login(conn, user) do
conn
|> assign(:current_user, user)
|> put_session(:user_id, user.id)
|> configure_session(renew: true)
end
def login(conn, email, given_pass) do
user = Passport.Config.repo.get_by(Passport.Config.resource, email: email)
cond do
user && checkpw(given_pass, user.password_hash) ->
{:ok, login(conn, user)}
user ->
{:error, :unauthorized, conn}
true ->
{:error, :not_found, conn}
end
end
def logout(conn) do
configure_session(conn, drop: true)
end
end
================================================
FILE: lib/passport.ex
================================================
defmodule Passport do
defmacro __using__(_) do
quote do
import Passport.Plug
end
end
end
================================================
FILE: mix.exs
================================================
defmodule Passport.Mixfile do
use Mix.Project
def project do
[app: :passport,
version: "0.1.0",
elixir: "~> 1.4",
build_embedded: Mix.env == :prod,
start_permanent: Mix.env == :prod,
deps: deps()]
end
# Configuration for the OTP application
#
# Type "mix help compile.app" for more information
def application do
# Specify extra applications you'll use from Erlang/Elixir
[extra_applications: [:logger]]
end
# Dependencies can be Hex packages:
#
# {:my_dep, "~> 0.3.0"}
#
# Or git/path repositories:
#
# {:my_dep, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}
#
# Type "mix help deps" for more examples and options
defp deps do
[
{:phoenix, "~> 1.3.0-rc"},
{:comeonin, "~> 3.0"}
]
end
end
================================================
FILE: priv/templates/account/account_context.ex
================================================
defmodule <%= inspect context.module %>.Registration do
use Ecto.Schema
import Ecto.Changeset
embedded_schema do
field :email
field :password
end
end
defmodule <%= inspect context.module %> do
@behaviour Passport.Account
import Ecto.{Query, Changeset}, warn: false
alias <%= inspect schema.repo %>
alias <%= inspect schema.module %>
alias <%= inspect context.base_module %>.Auth
alias <%= inspect context.module %>.Registration
def get_user(id), do: Repo.get(User, id)
def create_user(attrs \\ %{}) do
%User{}
|> user_changeset(attrs)
|> Repo.insert()
end
defp user_changeset(%User{} = user, attrs) do
user
|> cast(attrs, [:email])
|> validate_required([:email])
|> unique_constraint(:email)
end
def new_registration do
registration_changeset(%Registration{}, %{})
end
def create_registration(attrs \\ %{}) do
changeset = registration_changeset(%Registration{}, attrs)
with true <- changeset.valid?,
registration = Ecto.Changeset.apply_changes(changeset) do
Repo.transaction fn ->
case create_user(Map.take(registration, [:email])) do
{:ok, user} ->
Auth.create_password(%{password: registration.password, user_id: user.id})
{:error, error} ->
%{changeset | errors: error.errors, action: :insert}
|> Repo.rollback
end
end
else
_ -> {:error, %{changeset | action: :insert}}
end
end
defp registration_changeset(%Registration{} = registration, attrs) do
registration
|> cast(attrs, [:email, :password])
|> validate_confirmation(:password, required: true)
|> validate_required([:email])
|> validate_format(:email, ~r/.+@.+/)
end
end
================================================
FILE: priv/templates/account/user_migration.exs
================================================
defmodule <%= inspect schema.repo %>.Migrations.Create<%= inspect schema.module %> do
use Ecto.Migration
def change do
create table(:<%= schema.table %>) do
add :email, :string
timestamps()
end
create unique_index(:<%= schema.table %>, [:email])
end
end
================================================
FILE: priv/templates/account/user_schema.ex
================================================
defmodule <%= inspect schema.module %> do
use Ecto.Schema
schema <%= inspect schema.table %> do
field :email, :string
timestamps()
end
end
================================================
FILE: priv/templates/auth/auth_context.ex
================================================
defmodule <%= inspect context.module %> do
use Passport.Auth
import Ecto.{Query, Changeset}, warn: false
alias <%= inspect schema.module %>
alias <%= inspect schema.repo %>
def create_password(attrs \\ %{}) do
%Password{}
|> password_changeset(attrs)
|> Repo.insert()
end
defp password_changeset(%Password{} = password, attrs) do
password
|> cast(attrs, [:password_hash, :user_id])
|> put_hashed_password(attrs)
|> validate_required([:password_hash, :user_id])
end
defp put_hashed_password(changeset, %{password: pass}) do
put_change(changeset, :password_hash, Passport.Password.Crypto.hash(pass))
end
end
================================================
FILE: priv/templates/auth/password_migration.exs
================================================
defmodule <%= inspect schema.repo %>.Migrations.Create<%= inspect schema.module %> do
use Ecto.Migration
def change do
create table(:<%= schema.table %>) do
add :password_hash, :string
add :user_id, :integer
timestamps()
end
create index(:<%= schema.table %>, [:user_id])
end
end
================================================
FILE: priv/templates/auth/password_schema.ex
================================================
defmodule <%= inspect schema.module %> do
use Ecto.Schema
schema <%= inspect schema.table %> do
field :password_hash, :string
field :user_id, :integer
timestamps()
end
end
================================================
FILE: priv/templates/passport.install/migration.exs
================================================
defmodule <%= base %>.Repo.Migrations.Create<%= scoped %> do
use Ecto.Migration
def change do
create table(:<%= plural %>) do
add :email, :string, null: false
add :password_hash, :string
timestamps
end
create unique_index(:<%= plural %>, [:email])
end
end
================================================
FILE: priv/templates/passport.install/model.ex
================================================
defmodule <%= module %> do
use <%= base %>.Web, :model
alias Passport.Password
schema <%= inspect plural %> do
field :email, :string
field :password, :string, virtual: true
field :password_hash, :string
tim
gitextract_f4lfr0yp/
├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── config/
│ └── config.exs
├── example_app/
│ ├── .gitignore
│ ├── README.md
│ ├── brunch-config.js
│ ├── config/
│ │ ├── config.exs
│ │ ├── dev.exs
│ │ ├── prod.exs
│ │ ├── prod.secret.exs
│ │ └── test.exs
│ ├── lib/
│ │ ├── example_app/
│ │ │ ├── endpoint.ex
│ │ │ └── repo.ex
│ │ └── example_app.ex
│ ├── mix.exs
│ ├── package.json
│ ├── priv/
│ │ ├── gettext/
│ │ │ ├── en/
│ │ │ │ └── LC_MESSAGES/
│ │ │ │ └── errors.po
│ │ │ └── errors.pot
│ │ ├── repo/
│ │ │ ├── migrations/
│ │ │ │ └── 20160211110758_create_user.exs
│ │ │ └── seeds.exs
│ │ └── static/
│ │ └── robots.txt
│ ├── test/
│ │ ├── controllers/
│ │ │ └── page_controller_test.exs
│ │ ├── support/
│ │ │ ├── channel_case.ex
│ │ │ ├── conn_case.ex
│ │ │ └── model_case.ex
│ │ ├── test_helper.exs
│ │ └── views/
│ │ ├── error_view_test.exs
│ │ ├── layout_view_test.exs
│ │ └── page_view_test.exs
│ └── web/
│ ├── channels/
│ │ └── user_socket.ex
│ ├── controllers/
│ │ ├── page_controller.ex
│ │ ├── password_controller.ex
│ │ ├── registration_controller.ex
│ │ └── session_controller.ex
│ ├── gettext.ex
│ ├── models/
│ │ └── user.ex
│ ├── router.ex
│ ├── static/
│ │ ├── assets/
│ │ │ └── robots.txt
│ │ ├── css/
│ │ │ └── app.css
│ │ └── js/
│ │ ├── app.js
│ │ └── socket.js
│ ├── templates/
│ │ ├── layout/
│ │ │ └── app.html.eex
│ │ ├── page/
│ │ │ └── index.html.eex
│ │ ├── password/
│ │ │ └── forget_password.html.eex
│ │ ├── registration/
│ │ │ └── new.html.eex
│ │ └── session/
│ │ └── new.html.eex
│ ├── views/
│ │ ├── error_helpers.ex
│ │ ├── error_view.ex
│ │ ├── layout_view.ex
│ │ ├── page_view.ex
│ │ ├── password_view.ex
│ │ ├── registration_view.ex
│ │ └── session_view.ex
│ └── web.ex
├── lib/
│ ├── mix/
│ │ └── tasks/
│ │ ├── install.ex
│ │ └── passport.setup.ex
│ ├── passport/
│ │ ├── account.ex
│ │ ├── auth.ex
│ │ ├── auth_type/
│ │ │ ├── auth_type.ex
│ │ │ └── password/
│ │ │ ├── crypto.ex
│ │ │ └── password.ex
│ │ ├── config.ex
│ │ ├── plug.ex
│ │ ├── router.ex
│ │ └── session.ex
│ └── passport.ex
├── mix.exs
├── priv/
│ └── templates/
│ ├── account/
│ │ ├── account_context.ex
│ │ ├── user_migration.exs
│ │ └── user_schema.ex
│ ├── auth/
│ │ ├── auth_context.ex
│ │ ├── password_migration.exs
│ │ └── password_schema.ex
│ ├── passport.install/
│ │ ├── migration.exs
│ │ ├── model.ex
│ │ ├── password_controller.ex
│ │ ├── password_new.html.eex
│ │ ├── password_view.ex
│ │ ├── registration_controller.ex
│ │ ├── registration_new.html.eex
│ │ ├── registration_view.ex
│ │ ├── session_controller.ex
│ │ ├── session_new.html.eex
│ │ └── session_view.ex
│ └── web/
│ ├── login.html.eex
│ ├── register.html.eex
│ ├── registration_controller.ex
│ ├── registration_view.ex
│ ├── session_controller.ex
│ └── session_view.ex
└── test/
├── passport_test.exs
└── test_helper.exs
SYMBOL INDEX (127 symbols across 47 files)
FILE: example_app/lib/example_app.ex
class ExampleApp (line 1) | defmodule ExampleApp
method start (line 6) | def start(_type, _args) do
method config_change (line 26) | def config_change(changed, _new, removed) do
FILE: example_app/lib/example_app/endpoint.ex
class ExampleApp.Endpoint (line 1) | defmodule ExampleApp.Endpoint
FILE: example_app/lib/example_app/repo.ex
class ExampleApp.Repo (line 1) | defmodule ExampleApp.Repo
FILE: example_app/mix.exs
class ExampleApp.Mixfile (line 1) | defmodule ExampleApp.Mixfile
method project (line 4) | def project do
method application (line 19) | def application do
method elixirc_paths (line 26) | defp elixirc_paths(:test), do: ["lib", "web", "test/support"]
method elixirc_paths (line 27) | defp elixirc_paths(_), do: ["lib", "web"]
method deps (line 32) | defp deps do
method aliases (line 49) | defp aliases do
FILE: example_app/priv/repo/migrations/20160211110758_create_user.exs
class ExampleApp.Repo.Migrations.CreateUser (line 1) | defmodule ExampleApp.Repo.Migrations.CreateUser
method change (line 4) | def change do
FILE: example_app/test/controllers/page_controller_test.exs
class ExampleApp.PageControllerTest (line 1) | defmodule ExampleApp.PageControllerTest
FILE: example_app/test/support/channel_case.ex
class ExampleApp.ChannelCase (line 1) | defmodule ExampleApp.ChannelCase
FILE: example_app/test/support/conn_case.ex
class ExampleApp.ConnCase (line 1) | defmodule ExampleApp.ConnCase
FILE: example_app/test/support/model_case.ex
class ExampleApp.ModelCase (line 1) | defmodule ExampleApp.ModelCase
method errors_on (line 58) | def errors_on(model, data) do
FILE: example_app/test/views/error_view_test.exs
class ExampleApp.ErrorViewTest (line 1) | defmodule ExampleApp.ErrorViewTest
FILE: example_app/test/views/layout_view_test.exs
class ExampleApp.LayoutViewTest (line 1) | defmodule ExampleApp.LayoutViewTest
FILE: example_app/test/views/page_view_test.exs
class ExampleApp.PageViewTest (line 1) | defmodule ExampleApp.PageViewTest
FILE: example_app/web/channels/user_socket.ex
class ExampleApp.UserSocket (line 1) | defmodule ExampleApp.UserSocket
method connect (line 22) | def connect(_params, socket) do
method id (line 36) | def id(_socket), do: nil
FILE: example_app/web/controllers/page_controller.ex
class ExampleApp.PageController (line 1) | defmodule ExampleApp.PageController
method index (line 4) | def index(conn, _params) do
FILE: example_app/web/controllers/password_controller.ex
class ExampleApp.PasswordController (line 1) | defmodule ExampleApp.PasswordController
method forget_password (line 6) | def forget_password(conn, _) do
method reset_password (line 11) | def reset_password(conn, %{"user" => %{"email" => email}}) do
FILE: example_app/web/controllers/registration_controller.ex
class ExampleApp.RegistrationController (line 1) | defmodule ExampleApp.RegistrationController
method new (line 6) | def new(conn, _params) do
method create (line 12) | def create(conn, %{"user" => registration_params}) do
FILE: example_app/web/controllers/session_controller.ex
class ExampleApp.SessionController (line 1) | defmodule ExampleApp.SessionController
method new (line 8) | def new(conn, _) do
method create (line 13) | def create(conn, %{"session" => %{"email" => email, "password" => pass...
method delete (line 26) | def delete(conn, _) do
FILE: example_app/web/gettext.ex
class ExampleApp.Gettext (line 1) | defmodule ExampleApp.Gettext
FILE: example_app/web/models/user.ex
class ExampleApp.User (line 1) | defmodule ExampleApp.User
method changeset (line 13) | def changeset(model, params \\ :empty) do model
method registration_changeset (line 19) | def registration_changeset(model, params) do model
method put_hashed_password (line 26) | defp put_hashed_password(changeset) do
FILE: example_app/web/router.ex
class ExampleApp.Router (line 1) | defmodule ExampleApp.Router
FILE: example_app/web/views/error_helpers.ex
class ExampleApp.ErrorHelpers (line 1) | defmodule ExampleApp.ErrorHelpers
method error_tag (line 11) | def error_tag(form, field) do
method translate_error (line 20) | def translate_error({msg, opts}) do
method translate_error (line 32) | def translate_error(msg) do
FILE: example_app/web/views/error_view.ex
class ExampleApp.ErrorView (line 1) | defmodule ExampleApp.ErrorView
method render (line 4) | def render("404.html", _assigns) do
method render (line 8) | def render("500.html", _assigns) do
method template_not_found (line 14) | def template_not_found(_template, assigns) do
FILE: example_app/web/views/layout_view.ex
class ExampleApp.LayoutView (line 1) | defmodule ExampleApp.LayoutView
FILE: example_app/web/views/page_view.ex
class ExampleApp.PageView (line 1) | defmodule ExampleApp.PageView
FILE: example_app/web/views/password_view.ex
class ExampleApp.PasswordView (line 1) | defmodule ExampleApp.PasswordView
FILE: example_app/web/views/registration_view.ex
class ExampleApp.RegistrationView (line 1) | defmodule ExampleApp.RegistrationView
FILE: example_app/web/views/session_view.ex
class ExampleApp.SessionView (line 1) | defmodule ExampleApp.SessionView
FILE: example_app/web/web.ex
class ExampleApp.Web (line 1) | defmodule ExampleApp.Web
method model (line 19) | def model do
method controller (line 29) | def controller do
method view (line 42) | def view do
method router (line 58) | def router do
method channel (line 64) | def channel do
FILE: lib/mix/tasks/install.ex
class Mix.Tasks.Passport.Install (line 1) | defmodule Mix.Tasks.Passport.Install
method run (line 26) | def run(args) do
method validate_args! (line 110) | defp validate_args!([_singular, plural] = args) do
method validate_args! (line 119) | defp validate_args!([]) do
method validate_args! (line 123) | defp validate_args!(_) do
method raise_with_help (line 127) | defp raise_with_help do
method timestamp (line 139) | defp timestamp do
method pad (line 145) | defp pad(i), do: to_string(i)
method paths (line 147) | defp paths do
FILE: lib/mix/tasks/passport.setup.ex
class Mix.Tasks.Passport.Setup (line 1) | defmodule Mix.Tasks.Passport.Setup
method run (line 11) | def run(_) do
method generate_account (line 21) | defp generate_account(paths) do
method generate_auth (line 34) | defp generate_auth(paths) do
method generate_web (line 47) | defp generate_web(paths) do
method generate_config (line 66) | defp generate_config() do
method copy_new_files (line 86) | defp copy_new_files(_context, paths, binding) do
method print_shell_instructions (line 107) | defp print_shell_instructions() do
method timestamp (line 143) | defp timestamp do
method pad (line 149) | defp pad(i), do: to_string(i)
FILE: lib/passport.ex
class Passport (line 1) | defmodule Passport
FILE: lib/passport/account.ex
class Passport.Account (line 1) | defmodule Passport.Account
FILE: lib/passport/auth.ex
class Passport.Auth (line 1) | defmodule Passport.Auth
method plugs (line 12) | defp plugs() do
method do_login (line 82) | def do_login(conn, user) do
method define_enabled_type_defs (line 90) | defp define_enabled_type_defs() do
method get_account (line 106) | def get_account(params) do
FILE: lib/passport/auth_type/auth_type.ex
class Passport.AuthType (line 1) | defmodule Passport.AuthType
FILE: lib/passport/auth_type/password/crypto.ex
class Passport.Password.Crypto (line 1) | defmodule Passport.Password.Crypto
method hash (line 4) | def hash(password) do
method valid_password? (line 8) | def valid_password?(given_password, password_hash) do
FILE: lib/passport/auth_type/password/password.ex
class Passport.Password (line 1) | defmodule Passport.Password
method valid_credential? (line 11) | def valid_credential?(account, password) do
method save_credential (line 26) | def save_credential(credential) do
method update_credential (line 36) | def update_credential(credential) do
method delete_credential (line 43) | def delete_credential(credential) do
method get_active_password (line 51) | defp get_active_password(%{id: id}) do
method get_active_password (line 55) | defp get_active_password(_) do
FILE: lib/passport/config.ex
class Passport.Config (line 1) | defmodule Passport.Config
method default_config (line 12) | def default_config do
FILE: lib/passport/plug.ex
class Passport.Plug (line 1) | defmodule Passport.Plug
method current_user (line 5) | def current_user(conn, _) do
method authenticate (line 11) | def authenticate(conn, _) do
method authenticate_env (line 15) | defp authenticate_env(:test, conn) do
method authenticate_env (line 28) | defp authenticate_env(_, conn) do
method fetch_user_by_id (line 41) | defp fetch_user_by_id(id) do
FILE: lib/passport/session.ex
class Passport.Session (line 1) | defmodule Passport.Session
method login (line 5) | def login(conn, user) do
method login (line 12) | def login(conn, email, given_pass) do
method logout (line 25) | def logout(conn) do
FILE: mix.exs
class Passport.Mixfile (line 1) | defmodule Passport.Mixfile
method project (line 4) | def project do
method application (line 16) | def application do
method deps (line 30) | defp deps do
FILE: priv/templates/account/account_context.ex
function user_changeset (line 28) | defp user_changeset(%User{} = user, attrs) do
function new_registration (line 35) | def new_registration do
function create_registration (line 39) | def create_registration(attrs \\ %{}) do
FILE: priv/templates/auth/auth_context.ex
function create_password (line 8) | def create_password(attrs \\ %{}) do
function password_changeset (line 14) | defp password_changeset(%Password{} = password, attrs) do
function put_hashed_password (line 22) | defp put_hashed_password(changeset, %{password: pass}) do
FILE: priv/templates/passport.install/model.ex
function registration_changeset (line 21) | def registration_changeset(model, params) do
FILE: priv/templates/passport.install/password_controller.ex
function new (line 4) | def new(conn, _) do
function reset_password (line 10) | def reset_password(conn, %{"user" => %{"email" => _email}}) do
FILE: priv/templates/web/registration_controller.ex
function new (line 5) | def new(conn, _params) do
FILE: priv/templates/web/session_controller.ex
function new (line 4) | def new(conn, _) do
FILE: test/passport_test.exs
class PassportTest (line 1) | defmodule PassportTest
Condensed preview — 94 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (207K chars).
[
{
"path": ".gitignore",
"chars": 41,
"preview": "/_build\n/cover\n/deps\nerl_crash.dump\n*.ez\n"
},
{
"path": ".travis.yml",
"chars": 37,
"preview": "language: elixir\nelixir:\n - 1.4.0\n"
},
{
"path": "LICENSE",
"chars": 1105,
"preview": "LICENSE\n\nThe MIT License\n\nCopyright (c) 2017 Shankar Dhanasekaran and Opendrops.\n\nPermission is hereby granted, free of "
},
{
"path": "README.md",
"chars": 1214,
"preview": "# Passport\n## Experimental. \n\nPassport is an easy to use Authentication library for Phoenix 1.3.\n\nPassport is rewritten "
},
{
"path": "config/config.exs",
"chars": 1119,
"preview": "# This file is responsible for configuring your application\n# and its dependencies with the aid of the Mix.Config module"
},
{
"path": "example_app/.gitignore",
"chars": 569,
"preview": "# App artifacts\n/_build\n/db\n/deps\n/*.ez\n\n# Generate on crash by the VM\nerl_crash.dump\n\n# Static artifacts\n/node_modules\n"
},
{
"path": "example_app/README.md",
"chars": 698,
"preview": "# ExampleApp\n\nTo start your Phoenix app:\n\n 1. Install dependencies with `mix deps.get`\n 2. Create and migrate your dat"
},
{
"path": "example_app/brunch-config.js",
"chars": 1829,
"preview": "exports.config = {\n // See http://brunch.io/#documentation for docs.\n files: {\n javascripts: {\n joinTo: \"js/ap"
},
{
"path": "example_app/config/config.exs",
"chars": 1035,
"preview": "# This file is responsible for configuring your application\n# and its dependencies with the aid of the Mix.Config module"
},
{
"path": "example_app/config/dev.exs",
"chars": 1285,
"preview": "use Mix.Config\n\n# For development, we disable any cache and enable\n# debugging and code reloading.\n#\n# The watchers conf"
},
{
"path": "example_app/config/prod.exs",
"chars": 2203,
"preview": "use Mix.Config\n\n# For production, we configure the host to read the PORT\n# from the system environment. Therefore, you w"
},
{
"path": "example_app/config/prod.secret.exs",
"chars": 477,
"preview": "use Mix.Config\n\n# In this file, we keep production configuration that\n# you likely want to automate and keep it away fro"
},
{
"path": "example_app/config/test.exs",
"chars": 509,
"preview": "use Mix.Config\n\n# We don't run a server during test. If one is required,\n# you can enable the server option below.\nconfi"
},
{
"path": "example_app/lib/example_app/endpoint.ex",
"chars": 1029,
"preview": "defmodule ExampleApp.Endpoint do\n use Phoenix.Endpoint, otp_app: :example_app\n\n socket \"/socket\", ExampleApp.UserSocke"
},
{
"path": "example_app/lib/example_app/repo.ex",
"chars": 72,
"preview": "defmodule ExampleApp.Repo do\n use Ecto.Repo, otp_app: :example_app\nend\n"
},
{
"path": "example_app/lib/example_app.ex",
"chars": 994,
"preview": "defmodule ExampleApp do\n use Application\n\n # See http://elixir-lang.org/docs/stable/elixir/Application.html\n # for mo"
},
{
"path": "example_app/mix.exs",
"chars": 1568,
"preview": "defmodule ExampleApp.Mixfile do\n use Mix.Project\n\n def project do\n [app: :example_app,\n version: \"0.0.1\",\n "
},
{
"path": "example_app/package.json",
"chars": 341,
"preview": "{\n \"repository\": {\n },\n \"dependencies\": {\n \"babel-brunch\": \"^6.0.0\",\n \"brunch\": \"^2.1.1\",\n \"clean-css-brunch"
},
{
"path": "example_app/priv/gettext/en/LC_MESSAGES/errors.po",
"chars": 2414,
"preview": "## `msgid`s in this file come from POT (.pot) files. Do not add, change, or\n## remove `msgid`s manually here as they're "
},
{
"path": "example_app/priv/gettext/errors.pot",
"chars": 2446,
"preview": "## This file is a PO Template file. `msgid`s here are often extracted from\n## source code; add new translations manually"
},
{
"path": "example_app/priv/repo/migrations/20160211110758_create_user.exs",
"chars": 294,
"preview": "defmodule ExampleApp.Repo.Migrations.CreateUser do\n use Ecto.Migration\n\n def change do\n create table(:users) do\n "
},
{
"path": "example_app/priv/repo/seeds.exs",
"chars": 356,
"preview": "# Script for populating the database. You can run it as:\n#\n# mix run priv/repo/seeds.exs\n#\n# Inside the script, you "
},
{
"path": "example_app/priv/static/robots.txt",
"chars": 202,
"preview": "# See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file\n#\n# To ban all spiders"
},
{
"path": "example_app/test/controllers/page_controller_test.exs",
"chars": 199,
"preview": "defmodule ExampleApp.PageControllerTest do\n use ExampleApp.ConnCase\n\n test \"GET /\", %{conn: conn} do\n conn = get co"
},
{
"path": "example_app/test/support/channel_case.ex",
"chars": 974,
"preview": "defmodule ExampleApp.ChannelCase do\n @moduledoc \"\"\"\n This module defines the test case to be used by\n channel tests.\n"
},
{
"path": "example_app/test/support/conn_case.ex",
"chars": 1069,
"preview": "defmodule ExampleApp.ConnCase do\n @moduledoc \"\"\"\n This module defines the test case to be used by\n tests that require"
},
{
"path": "example_app/test/support/model_case.ex",
"chars": 1607,
"preview": "defmodule ExampleApp.ModelCase do\n @moduledoc \"\"\"\n This module defines the test case to be used by\n model tests.\n\n Y"
},
{
"path": "example_app/test/test_helper.exs",
"chars": 192,
"preview": "ExUnit.start\n\nMix.Task.run \"ecto.create\", ~w(-r ExampleApp.Repo --quiet)\nMix.Task.run \"ecto.migrate\", ~w(-r ExampleApp.R"
},
{
"path": "example_app/test/views/error_view_test.exs",
"chars": 583,
"preview": "defmodule ExampleApp.ErrorViewTest do\n use ExampleApp.ConnCase, async: true\n\n # Bring render/3 and render_to_string/3 "
},
{
"path": "example_app/test/views/layout_view_test.exs",
"chars": 81,
"preview": "defmodule ExampleApp.LayoutViewTest do\n use ExampleApp.ConnCase, async: true\nend"
},
{
"path": "example_app/test/views/page_view_test.exs",
"chars": 80,
"preview": "defmodule ExampleApp.PageViewTest do\n use ExampleApp.ConnCase, async: true\nend\n"
},
{
"path": "example_app/web/channels/user_socket.ex",
"chars": 1176,
"preview": "defmodule ExampleApp.UserSocket do\n use Phoenix.Socket\n\n ## Channels\n # channel \"rooms:*\", ExampleApp.RoomChannel\n\n "
},
{
"path": "example_app/web/controllers/page_controller.ex",
"chars": 144,
"preview": "defmodule ExampleApp.PageController do\n use ExampleApp.Web, :controller\n\n def index(conn, _params) do\n render conn,"
},
{
"path": "example_app/web/controllers/password_controller.ex",
"chars": 398,
"preview": "defmodule ExampleApp.PasswordController do\n use ExampleApp.Web, :controller\n\n alias ExampleApp.User\n\n def forget_pass"
},
{
"path": "example_app/web/controllers/registration_controller.ex",
"chars": 647,
"preview": "defmodule ExampleApp.RegistrationController do\n use ExampleApp.Web, :controller\n\n alias ExampleApp.User\n\n def new(con"
},
{
"path": "example_app/web/controllers/session_controller.ex",
"chars": 743,
"preview": "defmodule ExampleApp.SessionController do\n use ExampleApp.Web, :controller\n\n alias ExampleApp.User\n alias Passport.Se"
},
{
"path": "example_app/web/gettext.ex",
"chars": 710,
"preview": "defmodule ExampleApp.Gettext do\n @moduledoc \"\"\"\n A module providing Internationalization with a gettext-based API.\n\n "
},
{
"path": "example_app/web/models/user.ex",
"chars": 859,
"preview": "defmodule ExampleApp.User do\n use ExampleApp.Web, :model\n alias Passport.Password\n\n schema \"users\" do\n field :emai"
},
{
"path": "example_app/web/router.ex",
"chars": 932,
"preview": "defmodule ExampleApp.Router do\n use ExampleApp.Web, :router\n use Passport\n\n pipeline :browser do\n plug :accepts, ["
},
{
"path": "example_app/web/static/assets/robots.txt",
"chars": 202,
"preview": "# See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file\n#\n# To ban all spiders"
},
{
"path": "example_app/web/static/css/app.css",
"chars": 123881,
"preview": "/*!\n * Bootstrap v3.3.5 (http://getbootstrap.com)\n * Copyright 2011-2015 Twitter, Inc.\n * Licensed under MIT (https://gi"
},
{
"path": "example_app/web/static/js/app.js",
"chars": 677,
"preview": "// Brunch automatically concatenates all files in your\n// watched paths. Those paths can be configured at\n// config.path"
},
{
"path": "example_app/web/static/js/socket.js",
"chars": 2176,
"preview": "// NOTE: The contents of this file will only be executed if\n// you uncomment its entry in \"web/static/js/app.js\".\n\n// To"
},
{
"path": "example_app/web/templates/layout/app.html.eex",
"chars": 1469,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta charset=\"utf-8\">\n <meta http-equiv=\"X-UA-Compatible\" content=\"IE="
},
{
"path": "example_app/web/templates/page/index.html.eex",
"chars": 972,
"preview": "<div class=\"jumbotron\">\n <h2><%= gettext \"Welcome to %{name}\", name: \"Phoenix!\" %></h2>\n <p class=\"lead\">A productive "
},
{
"path": "example_app/web/templates/password/forget_password.html.eex",
"chars": 298,
"preview": "<h3>Request new password</h3>\n<%= form_for @conn, password_path(@conn, :reset_password), [as: :user], fn f -> %>\n\n <div"
},
{
"path": "example_app/web/templates/registration/new.html.eex",
"chars": 722,
"preview": "<h1>Register</h1>\n<%= form_for @changeset, registration_path(@conn, :create), fn f -> %>\n <%= if f.errors != [] do %>\n "
},
{
"path": "example_app/web/templates/session/new.html.eex",
"chars": 389,
"preview": "<h1>Login</h1>\n<%= form_for @conn, session_path(@conn, :create), [as: :session], fn f -> %>\n <div class=\"form-group\">\n "
},
{
"path": "example_app/web/views/error_helpers.ex",
"chars": 1006,
"preview": "defmodule ExampleApp.ErrorHelpers do\n @moduledoc \"\"\"\n Conveniences for translating and building error messages.\n \"\"\"\n"
},
{
"path": "example_app/web/views/error_view.ex",
"chars": 380,
"preview": "defmodule ExampleApp.ErrorView do\n use ExampleApp.Web, :view\n\n def render(\"404.html\", _assigns) do\n \"Page not found"
},
{
"path": "example_app/web/views/layout_view.ex",
"chars": 67,
"preview": "defmodule ExampleApp.LayoutView do\n use ExampleApp.Web, :view\nend\n"
},
{
"path": "example_app/web/views/page_view.ex",
"chars": 65,
"preview": "defmodule ExampleApp.PageView do\n use ExampleApp.Web, :view\nend\n"
},
{
"path": "example_app/web/views/password_view.ex",
"chars": 69,
"preview": "defmodule ExampleApp.PasswordView do\n use ExampleApp.Web, :view\nend\n"
},
{
"path": "example_app/web/views/registration_view.ex",
"chars": 73,
"preview": "defmodule ExampleApp.RegistrationView do\n use ExampleApp.Web, :view\nend\n"
},
{
"path": "example_app/web/views/session_view.ex",
"chars": 68,
"preview": "defmodule ExampleApp.SessionView do\n use ExampleApp.Web, :view\nend\n"
},
{
"path": "example_app/web/web.ex",
"chars": 1725,
"preview": "defmodule ExampleApp.Web do\n @moduledoc \"\"\"\n A module that keeps using definitions for controllers,\n views and so on."
},
{
"path": "lib/mix/tasks/install.ex",
"chars": 4862,
"preview": "defmodule Mix.Tasks.Passport.Install do\n use Mix.Task\n\n @shortdoc \"Generates controller, model and views for authentic"
},
{
"path": "lib/mix/tasks/passport.setup.ex",
"chars": 5861,
"preview": "defmodule Mix.Tasks.Passport.Setup do\n use Mix.Task\n\n alias Mix.Phoenix.Context\n @shortdoc \"Generates controller, mod"
},
{
"path": "lib/passport/account.ex",
"chars": 178,
"preview": "defmodule Passport.Account do\n @callback get_user(String.t) :: map\n\n # defmacro __using__(opts) do\n # quote do\n # "
},
{
"path": "lib/passport/auth.ex",
"chars": 3116,
"preview": "defmodule Passport.Auth do\n import Plug.Conn\n defmacro __using__(_opts) do\n quote do\n import Plug.Conn\n i"
},
{
"path": "lib/passport/auth_type/auth_type.ex",
"chars": 227,
"preview": "defmodule Passport.AuthType do\n @callback valid_credential?(map, String.t) :: map\n @callback save_credential(map) :: a"
},
{
"path": "lib/passport/auth_type/password/crypto.ex",
"chars": 264,
"preview": "defmodule Passport.Password.Crypto do\n import Comeonin.Bcrypt, only: [checkpw: 2, hashpwsalt: 1]\n\n def hash(password) "
},
{
"path": "lib/passport/auth_type/password/password.ex",
"chars": 1239,
"preview": "defmodule Passport.Password do\n @behaviour Passport.AuthType\n\n alias Passport.Config\n import Passport.Password.Crypto"
},
{
"path": "lib/passport/config.ex",
"chars": 441,
"preview": "defmodule Passport.Config do\n @default_config [\n repo: \"nil\",\n account_module: \"nil\",\n account_user: \"nil\",\n "
},
{
"path": "lib/passport/plug.ex",
"chars": 1031,
"preview": "defmodule Passport.Plug do\n import Plug.Conn\n import Phoenix.Controller, only: [redirect: 2, put_flash: 3]\n\n def curr"
},
{
"path": "lib/passport/router.ex",
"chars": 0,
"preview": ""
},
{
"path": "lib/passport/session.ex",
"chars": 659,
"preview": "defmodule Passport.Session do\n import Plug.Conn\n import Comeonin.Bcrypt, only: [checkpw: 2]\n\n def login(conn, user) d"
},
{
"path": "lib/passport.ex",
"chars": 107,
"preview": "defmodule Passport do\n defmacro __using__(_) do\n quote do\n import Passport.Plug\n end\n end\nend\n"
},
{
"path": "mix.exs",
"chars": 809,
"preview": "defmodule Passport.Mixfile do\n use Mix.Project\n\n def project do\n [app: :passport,\n version: \"0.1.0\",\n elixi"
},
{
"path": "priv/templates/account/account_context.ex",
"chars": 1765,
"preview": "defmodule <%= inspect context.module %>.Registration do\n use Ecto.Schema\n import Ecto.Changeset\n\n embedded_schema do\n"
},
{
"path": "priv/templates/account/user_migration.exs",
"chars": 287,
"preview": "defmodule <%= inspect schema.repo %>.Migrations.Create<%= inspect schema.module %> do\n use Ecto.Migration\n\n def change"
},
{
"path": "priv/templates/account/user_schema.ex",
"chars": 155,
"preview": "defmodule <%= inspect schema.module %> do\n use Ecto.Schema\n\n schema <%= inspect schema.table %> do\n field :email, :"
},
{
"path": "priv/templates/auth/auth_context.ex",
"chars": 664,
"preview": "defmodule <%= inspect context.module %> do\n use Passport.Auth\n import Ecto.{Query, Changeset}, warn: false\n\n alias <%"
},
{
"path": "priv/templates/auth/password_migration.exs",
"chars": 319,
"preview": "defmodule <%= inspect schema.repo %>.Migrations.Create<%= inspect schema.module %> do\n use Ecto.Migration\n\n def change"
},
{
"path": "priv/templates/auth/password_schema.ex",
"chars": 192,
"preview": "defmodule <%= inspect schema.module %> do\n use Ecto.Schema\n\n schema <%= inspect schema.table %> do\n field :password"
},
{
"path": "priv/templates/passport.install/migration.exs",
"chars": 301,
"preview": "defmodule <%= base %>.Repo.Migrations.Create<%= scoped %> do\n use Ecto.Migration\n\n def change do\n create table(:<%="
},
{
"path": "priv/templates/passport.install/model.ex",
"chars": 942,
"preview": "defmodule <%= module %> do\n use <%= base %>.Web, :model\n alias Passport.Password\n\n schema <%= inspect plural %> do\n "
},
{
"path": "priv/templates/passport.install/password_controller.ex",
"chars": 361,
"preview": "defmodule <%= base %>.PasswordController do\n use <%= base %>.Web, :controller\n\n def new(conn, _) do\n conn\n |> re"
},
{
"path": "priv/templates/passport.install/password_new.html.eex",
"chars": 304,
"preview": "<h3>Request new password</h3>\n<%%= form_for @conn, password_path(@conn, :reset), [as: :<%= singular %>], fn f -> %>\n\n <"
},
{
"path": "priv/templates/passport.install/password_view.ex",
"chars": 71,
"preview": "defmodule <%= base %>.PasswordView do\n use <%= base %>.Web, :view\nend\n"
},
{
"path": "priv/templates/passport.install/registration_controller.ex",
"chars": 690,
"preview": "defmodule <%= base %>.RegistrationController do\n use <%= base %>.Web, :controller\n\n alias <%= module %>\n\n def new(con"
},
{
"path": "priv/templates/passport.install/registration_new.html.eex",
"chars": 733,
"preview": "<h1>Register</h1>\n<%%= form_for @changeset, registration_path(@conn, :create), fn f -> %>\n <%%= if f.errors != [] do %>"
},
{
"path": "priv/templates/passport.install/registration_view.ex",
"chars": 75,
"preview": "defmodule <%= base %>.RegistrationView do\n use <%= base %>.Web, :view\nend\n"
},
{
"path": "priv/templates/passport.install/session_controller.ex",
"chars": 720,
"preview": "defmodule <%= base %>.SessionController do\n use <%= base %>.Web, :controller\n\n alias Passport.Session\n\n def new(conn,"
},
{
"path": "priv/templates/passport.install/session_new.html.eex",
"chars": 394,
"preview": "<h1>Login</h1>\n<%%= form_for @conn, session_path(@conn, :create), [as: :session], fn f -> %>\n <div class=\"form-group\">\n"
},
{
"path": "priv/templates/passport.install/session_view.ex",
"chars": 70,
"preview": "defmodule <%= base %>.SessionView do\n use <%= base %>.Web, :view\nend\n"
},
{
"path": "priv/templates/web/login.html.eex",
"chars": 460,
"preview": "<div class=\"col-md-6 col-md-offset-3\">\n <h1>Login</h1>\n <%%= form_for @conn, session_path(@conn, :create), [as: :sessi"
},
{
"path": "priv/templates/web/register.html.eex",
"chars": 872,
"preview": "<div class=\"col-md-6 col-md-offset-3\">\n <h1>Register</h1>\n <%%= form_for @changeset, registration_path(@conn, :create)"
},
{
"path": "priv/templates/web/registration_controller.ex",
"chars": 618,
"preview": "defmodule <%= web_module %>.RegistrationController do\n use <%= web_module %>, :controller\n alias <%= account_module %>"
},
{
"path": "priv/templates/web/registration_view.ex",
"chars": 83,
"preview": "defmodule <%= web_module %>.RegistrationView do\n use <%= web_module %>, :view\nend\n"
},
{
"path": "priv/templates/web/session_controller.ex",
"chars": 638,
"preview": "defmodule <%= web_module %>.SessionController do\n use <%= web_module %>, :controller\n alias <%= auth_module %>\n def n"
},
{
"path": "priv/templates/web/session_view.ex",
"chars": 78,
"preview": "defmodule <%= web_module %>.SessionView do\n use <%= web_module %>, :view\nend\n"
},
{
"path": "test/passport_test.exs",
"chars": 118,
"preview": "defmodule PassportTest do\n use ExUnit.Case\n doctest Passport\n\n test \"the truth\" do\n assert 1 + 1 == 2\n end\nend\n"
},
{
"path": "test/test_helper.exs",
"chars": 15,
"preview": "ExUnit.start()\n"
}
]
About this extraction
This page contains the full source code of the opendrops/passport GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 94 files (191.6 KB), approximately 57.9k tokens, and a symbol index with 127 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.