The response has been limited to 50k tokens of the smallest files in the repo. You can remove this limitation by removing the max tokens filter.
├── .gitignore
├── CHANGES
├── LICENSE
├── README.md
├── data
    ├── etc
    │   └── pritunl.conf
    ├── init.d.sysvinit
    │   └── pritunl
    ├── init.d.upstart
    │   └── pritunl
    ├── init
    │   └── pritunl.conf
    ├── systemd
    │   ├── pritunl-web.service
    │   └── pritunl.service
    └── var
    │   ├── pritunl.log
    │   └── pritunl.log.1
├── pritunl
    ├── __init__.py
    ├── __main__.py
    ├── acme.py
    ├── acmetiny.py
    ├── app.py
    ├── auth
    │   ├── __init__.py
    │   ├── administrator.py
    │   ├── app.py
    │   ├── csrf.py
    │   └── utils.py
    ├── authorizer
    │   ├── __init__.py
    │   └── authorizer.py
    ├── cache.py
    ├── cachelocal
    │   ├── __init__.py
    │   └── cache_trie.py
    ├── callbacks
    │   ├── __init__.py
    │   └── callbacks.py
    ├── callqueue.py
    ├── clients
    │   ├── __init__.py
    │   └── clients.py
    ├── constants.py
    ├── database
    │   ├── __init__.py
    │   └── utils.py
    ├── docdb.py
    ├── event.py
    ├── exceptions.py
    ├── firewall
    │   ├── __init__.py
    │   └── firewall.py
    ├── handlers
    │   ├── __init__.py
    │   ├── admin.py
    │   ├── auth.py
    │   ├── before_request.py
    │   ├── device.py
    │   ├── errors.py
    │   ├── event.py
    │   ├── host.py
    │   ├── key.py
    │   ├── link.py
    │   ├── log.py
    │   ├── logs.py
    │   ├── org.py
    │   ├── ping.py
    │   ├── robots.py
    │   ├── server.py
    │   ├── settings.py
    │   ├── sso.py
    │   ├── static.py
    │   ├── status.py
    │   ├── subscription.py
    │   └── user.py
    ├── helpers.py
    ├── host
    │   ├── __init__.py
    │   ├── host.py
    │   ├── usage.py
    │   ├── usage_utils.py
    │   └── utils.py
    ├── ipaddress.py
    ├── iptables.py
    ├── journal
    │   ├── __init__.py
    │   └── events.py
    ├── limiter.py
    ├── link
    │   ├── __init__.py
    │   ├── link.py
    │   └── utils.py
    ├── listener.py
    ├── logger
    │   ├── __init__.py
    │   ├── entry.py
    │   ├── filter.py
    │   ├── formatter.py
    │   ├── handler.py
    │   └── view.py
    ├── messenger.py
    ├── mongo
    │   ├── __init__.py
    │   ├── dict.py
    │   ├── list.py
    │   └── object.py
    ├── monitoring
    │   ├── __init__.py
    │   └── utils.py
    ├── ntplib.py
    ├── objcache.py
    ├── organization
    │   ├── __init__.py
    │   ├── organization.py
    │   └── utils.py
    ├── patches.py
    ├── plugins
    │   ├── __init__.py
    │   ├── example.py
    │   ├── plugins.py
    │   └── utils.py
    ├── pooler.py
    ├── poolers
    │   ├── __init__.py
    │   ├── dh_params.py
    │   ├── org.py
    │   └── user.py
    ├── pyrad
    │   ├── __init__.py
    │   ├── bidict.py
    │   ├── client.py
    │   ├── curved.py
    │   ├── dictfile.py
    │   ├── dictionary.py
    │   ├── host.py
    │   ├── packet.py
    │   ├── proxy.py
    │   ├── server.py
    │   └── tools.py
    ├── queue
    │   ├── __init__.py
    │   ├── com.py
    │   ├── queue.py
    │   └── utils.py
    ├── queues
    │   ├── __init__.py
    │   ├── assign_ip_addr.py
    │   ├── assign_ip_pool.py
    │   ├── dh_params.py
    │   ├── init_org_pooled.py
    │   ├── init_user.py
    │   ├── init_user_pooled.py
    │   └── unassign_ip_addr.py
    ├── radius.py
    ├── runners
    │   ├── __init__.py
    │   ├── event.py
    │   ├── firewall.py
    │   ├── host.py
    │   ├── instance.py
    │   ├── journal.py
    │   ├── limiter.py
    │   ├── listener.py
    │   ├── logger.py
    │   ├── queue.py
    │   ├── server.py
    │   ├── settings.py
    │   ├── subscription.py
    │   ├── task.py
    │   ├── time_sync.py
    │   ├── tokens.py
    │   ├── transaction.py
    │   ├── update_server.py
    │   └── updates.py
    ├── server
    │   ├── __init__.py
    │   ├── bandwidth.py
    │   ├── bridge.py
    │   ├── instance.py
    │   ├── instance_com.py
    │   ├── instance_link.py
    │   ├── ip_pool.py
    │   ├── listener.py
    │   ├── output.py
    │   ├── output_link.py
    │   ├── server.py
    │   └── utils.py
    ├── settings
    │   ├── __init__.py
    │   ├── app.py
    │   ├── conf.py
    │   ├── group_base.py
    │   ├── group_file.py
    │   ├── group_local.py
    │   ├── group_mongo.py
    │   ├── local.py
    │   ├── mongo.py
    │   ├── settings.py
    │   ├── user.py
    │   └── vpn.py
    ├── setup
    │   ├── __init__.py
    │   ├── boto_conf.py
    │   ├── cache.py
    │   ├── check.py
    │   ├── clean.py
    │   ├── demo.py
    │   ├── dns.py
    │   ├── handlers.py
    │   ├── host.py
    │   ├── host_fix.py
    │   ├── local.py
    │   ├── logger.py
    │   ├── mongo.py
    │   ├── monitoring.py
    │   ├── ndppd.py
    │   ├── plugins.py
    │   ├── poolers.py
    │   ├── public_ip.py
    │   ├── runners.py
    │   ├── server.py
    │   ├── server_fix.py
    │   ├── server_listeners.py
    │   ├── settings.py
    │   ├── signal_handler.py
    │   ├── subscription.py
    │   ├── temp_path.py
    │   ├── token.py
    │   └── vault.py
    ├── sso
    │   ├── __init__.py
    │   ├── authzero.py
    │   ├── azure.py
    │   ├── duo.py
    │   ├── google.py
    │   ├── jumpcloud.py
    │   ├── okta.py
    │   ├── onelogin.py
    │   ├── radius.py
    │   ├── token.py
    │   ├── utils.py
    │   └── yubico.py
    ├── static
    │   ├── __init__.py
    │   ├── static.py
    │   └── utils.py
    ├── subscription.py
    ├── system
    │   ├── __init__.py
    │   └── sysctl.py
    ├── task.py
    ├── tasks
    │   ├── __init__.py
    │   ├── acme_update.py
    │   ├── clean_client_pool.py
    │   ├── clean_ip_pool.py
    │   ├── clean_network_links.py
    │   ├── clean_network_lock.py
    │   ├── clean_servers.py
    │   ├── clean_users.py
    │   ├── clean_vxlans.py
    │   ├── host.py
    │   ├── link.py
    │   ├── pooler.py
    │   ├── route.py
    │   ├── server.py
    │   └── sync_ip_pool.py
    ├── transaction
    │   ├── __init__.py
    │   ├── action.py
    │   ├── collection.py
    │   └── transaction.py
    ├── tunldb.py
    ├── upgrade
    │   ├── __init__.py
    │   ├── upgrade_1_17.py
    │   ├── upgrade_1_18.py
    │   ├── upgrade_1_24.py
    │   ├── upgrade_1_4.py
    │   ├── upgrade_1_5.py
    │   └── utils.py
    ├── user
    │   ├── __init__.py
    │   ├── user.py
    │   └── utils.py
    ├── utils
    │   ├── __init__.py
    │   ├── auth.py
    │   ├── aws.py
    │   ├── cert.py
    │   ├── filter.py
    │   ├── json_helpers.py
    │   ├── least_common_counter.py
    │   ├── mail.py
    │   ├── md5_hash.py
    │   ├── misc.py
    │   ├── network.py
    │   ├── none_queue.py
    │   ├── oracle.py
    │   ├── proc.py
    │   └── sig.py
    ├── vault
    │   ├── __init__.py
    │   ├── batch.py
    │   ├── item.py
    │   ├── nonces.py
    │   ├── utils.py
    │   └── vault.py
    └── vxlan
    │   ├── __init__.py
    │   └── vxlan.py
├── requirements.txt
├── selinux
    ├── pritunl.fc
    ├── pritunl.te
    ├── pritunl_dns.fc
    ├── pritunl_dns.te
    ├── pritunl_web.fc
    └── pritunl_web.te
├── selinux8
    ├── pritunl.fc
    ├── pritunl.te
    ├── pritunl_dns.fc
    ├── pritunl_dns.te
    ├── pritunl_web.fc
    └── pritunl_web.te
├── selinux9
    ├── pritunl.fc
    ├── pritunl.te
    ├── pritunl_dns.fc
    ├── pritunl_dns.te
    ├── pritunl_web.fc
    └── pritunl_web.te
├── server.py
├── setup.py
├── tools
    ├── add_aws_ranges.py
    ├── ami_init.sh
    ├── ami_mongo_init.sh
    ├── aws
    │   ├── pritunl-db.template
    │   └── pritunl.template
    ├── build.sh
    ├── builder.py
    ├── clean_capitalization.py
    ├── development_pritunl.conf
    ├── devices_sync.py
    ├── grafana.json
    ├── stress_testing
    │   ├── README.md
    │   ├── add_test_users.py
    │   ├── connect_all.go
    │   ├── download_all_users.py
    │   ├── find_missing.py
    │   ├── get_test_names.py
    │   ├── names
    │   ├── terraform
    │   │   └── pritunl.tf
    │   └── test_client
    │   │   ├── Dockerfile
    │   │   ├── client.go
    │   │   ├── commander.go
    │   │   └── controller.go
    ├── test_pritunl.py
    └── vagrant_provision.sh
└── www
    ├── Gruntfile.js
    ├── collections
        ├── admin.js
        ├── adminAudit.js
        ├── device.js
        ├── event.js
        ├── host.js
        ├── link.js
        ├── linkLocation.js
        ├── log.js
        ├── org.js
        ├── server.js
        ├── serverHost.js
        ├── serverLink.js
        ├── serverOrg.js
        ├── serverRoute.js
        ├── user.js
        ├── userAudit.js
        ├── userDevice.js
        └── userServer.js
    ├── dart
        ├── lib
        │   ├── alert.dart
        │   ├── all_aware.dart
        │   ├── bases
        │   │   ├── form_control
        │   │   │   └── form_control.dart
        │   │   └── modal_content
        │   │   │   └── modal_content.dart
        │   ├── collection.dart
        │   ├── collections
        │   │   ├── collections.dart
        │   │   ├── events.dart
        │   │   ├── log_entries.dart
        │   │   ├── organizations.dart
        │   │   ├── server_hosts.dart
        │   │   ├── server_orgs.dart
        │   │   ├── servers.dart
        │   │   └── users.dart
        │   ├── components
        │   │   ├── alert
        │   │   │   ├── alert.dart
        │   │   │   └── alert.scss
        │   │   ├── alert_global
        │   │   │   └── alert_global.dart
        │   │   ├── boilerplate
        │   │   │   ├── boilerplate.dart
        │   │   │   ├── boilerplate.html
        │   │   │   └── boilerplate.scss
        │   │   ├── box_label
        │   │   │   ├── box_label.dart
        │   │   │   └── box_label.scss
        │   │   ├── btn
        │   │   │   ├── btn.dart
        │   │   │   └── btn.scss
        │   │   ├── checkbox
        │   │   │   ├── checkbox.dart
        │   │   │   └── checkbox.scss
        │   │   ├── components.dart
        │   │   ├── container
        │   │   │   ├── container.dart
        │   │   │   └── container.scss
        │   │   ├── editor
        │   │   │   ├── editor.dart
        │   │   │   └── editor.scss
        │   │   ├── form_group
        │   │   │   ├── form_group.dart
        │   │   │   └── form_group.scss
        │   │   ├── form_input
        │   │   │   ├── form_input.dart
        │   │   │   └── form_input.scss
        │   │   ├── form_select
        │   │   │   ├── form_select.dart
        │   │   │   └── form_select.scss
        │   │   ├── form_textarea
        │   │   │   ├── form_textarea.dart
        │   │   │   └── form_textarea.scss
        │   │   ├── fraction
        │   │   │   ├── fraction.dart
        │   │   │   └── fraction.scss
        │   │   ├── glyphicon
        │   │   │   ├── glyphicon.dart
        │   │   │   └── glyphicon.scss
        │   │   ├── log_entries
        │   │   │   ├── log_entries.dart
        │   │   │   ├── log_entries.html
        │   │   │   └── log_entries.scss
        │   │   ├── modal
        │   │   │   ├── modal.dart
        │   │   │   ├── modal.html
        │   │   │   └── modal.scss
        │   │   ├── navbar
        │   │   │   ├── navbar.dart
        │   │   │   ├── navbar.html
        │   │   │   └── navbar.scss
        │   │   ├── org_add
        │   │   │   ├── org_add.dart
        │   │   │   └── org_add.html
        │   │   ├── org_del
        │   │   │   ├── org_del.dart
        │   │   │   └── org_del.html
        │   │   ├── org_modify
        │   │   │   ├── org_modify.dart
        │   │   │   └── org_modify.html
        │   │   ├── organization
        │   │   │   ├── organization.dart
        │   │   │   ├── organization.html
        │   │   │   └── organization.scss
        │   │   ├── organizations
        │   │   │   ├── organizations.dart
        │   │   │   ├── organizations.html
        │   │   │   └── organizations.scss
        │   │   ├── qrcode
        │   │   │   ├── qrcode.dart
        │   │   │   └── qrcode.html
        │   │   ├── server
        │   │   │   ├── server.dart
        │   │   │   ├── server.html
        │   │   │   └── server.scss
        │   │   ├── server_del
        │   │   │   ├── server_del.dart
        │   │   │   └── server_del.html
        │   │   ├── servers
        │   │   │   ├── servers.dart
        │   │   │   ├── servers.html
        │   │   │   └── servers.scss
        │   │   ├── status
        │   │   │   ├── status.dart
        │   │   │   ├── status.html
        │   │   │   └── status.scss
        │   │   ├── user
        │   │   │   ├── user.dart
        │   │   │   ├── user.html
        │   │   │   └── user.scss
        │   │   ├── user_add
        │   │   │   ├── user_add.dart
        │   │   │   └── user_add.html
        │   │   ├── user_add_bulk
        │   │   │   ├── user_add_bulk.dart
        │   │   │   └── user_add_bulk.html
        │   │   ├── user_del
        │   │   │   ├── user_del.dart
        │   │   │   ├── user_del.html
        │   │   │   └── user_del.scss
        │   │   ├── user_email
        │   │   │   ├── user_email.dart
        │   │   │   ├── user_email.html
        │   │   │   └── user_email.scss
        │   │   ├── user_key_links
        │   │   │   ├── user_key_links.dart
        │   │   │   ├── user_key_links.html
        │   │   │   └── user_key_links.scss
        │   │   ├── user_modify
        │   │   │   ├── user_modify.dart
        │   │   │   └── user_modify.html
        │   │   └── user_otp
        │   │   │   ├── user_otp.dart
        │   │   │   ├── user_otp.html
        │   │   │   └── user_otp.scss
        │   ├── decorators
        │   │   ├── autofocus.dart
        │   │   ├── conditional.dart
        │   │   ├── decorators.dart
        │   │   ├── modal.dart
        │   │   ├── modal_attach.dart
        │   │   ├── noselect.dart
        │   │   ├── shift_click.dart
        │   │   └── tooltip.dart
        │   ├── exceptions.dart
        │   ├── fonts
        │   │   ├── FontAwesome.otf
        │   │   ├── fontawesome-webfont.eot
        │   │   ├── fontawesome-webfont.svg
        │   │   ├── fontawesome-webfont.ttf
        │   │   ├── fontawesome-webfont.woff
        │   │   ├── fredoka-one.eot
        │   │   ├── fredoka-one.woff
        │   │   ├── glyphicons-halflings-regular.eot
        │   │   ├── glyphicons-halflings-regular.svg
        │   │   ├── glyphicons-halflings-regular.ttf
        │   │   ├── glyphicons-halflings-regular.woff
        │   │   ├── ubuntu-bold.eot
        │   │   ├── ubuntu-bold.woff
        │   │   ├── ubuntu.eot
        │   │   └── ubuntu.woff
        │   ├── formatters
        │   │   ├── capitalize.dart
        │   │   ├── datetime.dart
        │   │   ├── formatters.dart
        │   │   ├── fraction.dart
        │   │   ├── slash.dart
        │   │   └── timer.dart
        │   ├── logger.dart
        │   ├── model.dart
        │   ├── models
        │   │   ├── event.dart
        │   │   ├── key.dart
        │   │   ├── log_entry.dart
        │   │   ├── models.dart
        │   │   ├── organization.dart
        │   │   ├── server.dart
        │   │   ├── server_host.dart
        │   │   ├── server_link_output.dart
        │   │   ├── server_org.dart
        │   │   ├── server_output.dart
        │   │   ├── status.dart
        │   │   └── user.dart
        │   ├── pritunl.dart
        │   ├── remote.dart
        │   ├── routers
        │   │   ├── main.dart
        │   │   └── routers.dart
        │   ├── settings
        │   │   └── settings.dart
        │   ├── styles
        │   │   ├── base.scss
        │   │   ├── colors.scss
        │   │   ├── globals.scss
        │   │   ├── mixins.scss
        │   │   ├── variables.scss
        │   │   └── vendor
        │   │   │   └── bootstrap.scss
        │   ├── transformers
        │   │   └── sass.dart
        │   ├── utils
        │   │   └── utils.dart
        │   └── views
        │   │   ├── dashboard.html
        │   │   ├── servers.html
        │   │   └── users.html
        ├── pubspec.lock
        ├── pubspec.yaml
        └── web
        │   ├── index.html
        │   ├── main.dart
        │   └── vendor
        │       ├── ace
        │           ├── ace.js
        │           ├── mode-log.js
        │           ├── mode-sh.js
        │           ├── mode-text.js
        │           ├── theme-chrome.js
        │           ├── theme-github.js
        │           └── theme-pritunl.js
        │       ├── qrcode.js
        │       └── qrcode.min.js
    ├── dbconf.html
    ├── demo
        ├── ajax.js
        ├── data.js
        ├── demo.html
        ├── demo.ovpn
        └── demo.tar
    ├── duo.html
    ├── fonts
        ├── FontAwesome.otf
        ├── fontawesome-webfont.eot
        ├── fontawesome-webfont.svg
        ├── fontawesome-webfont.ttf
        ├── fontawesome-webfont.woff
        ├── fontawesome-webfont.woff2
        ├── fredoka-one.eot
        ├── fredoka-one.woff
        ├── glyphicons-halflings-regular.eot
        ├── glyphicons-halflings-regular.svg
        ├── glyphicons-halflings-regular.ttf
        ├── glyphicons-halflings-regular.woff
        ├── ubuntu-bold.eot
        ├── ubuntu-bold.woff
        ├── ubuntu.eot
        └── ubuntu.woff
    ├── img
        ├── favicon.ico
        ├── header_logo.png
        ├── header_logo.xcf
        ├── logo.svg
        ├── logo100.png
        ├── logo14.png
        ├── logo140.png
        ├── logo16.png
        ├── logo192.png
        ├── logo256.png
        ├── logo32.png
        ├── logo512.png
        ├── logo64.png
        ├── logo_code.png
        ├── logo_full.png
        ├── logo_full.xcf
        ├── logo_full2.png
        ├── logo_full2.xcf
        ├── logo_full3.png
        ├── logo_full3.xcf
        ├── logo_stripe.png
        └── logo_stripe.svg
    ├── index.html
    ├── init
        ├── demo.js
        ├── production.js
        └── testing.js
    ├── key_view.html
    ├── key_view_dark.html
    ├── login.html
    ├── logo.png
    ├── main.js
    ├── models
        ├── admin.js
        ├── authSession.js
        ├── device.js
        ├── event.js
        ├── host.js
        ├── hostUsage.js
        ├── key.js
        ├── link.js
        ├── linkHost.js
        ├── linkHostConf.js
        ├── linkHostUri.js
        ├── linkLocation.js
        ├── linkPeer.js
        ├── linkRoute.js
        ├── linkRouteExclude.js
        ├── linkTransit.js
        ├── log.js
        ├── logs.js
        ├── org.js
        ├── server.js
        ├── serverBandwidth.js
        ├── serverHost.js
        ├── serverLink.js
        ├── serverOrg.js
        ├── serverOutput.js
        ├── serverOutputLink.js
        ├── serverRoute.js
        ├── settings.js
        ├── state.js
        ├── status.js
        ├── subscription.js
        ├── user.js
        ├── userAudit.js
        ├── userBulk.js
        ├── userDevice.js
        ├── userServer.js
        └── zones.js
    ├── package-lock.json
    ├── package.json
    ├── root
        ├── demo_index.html
        ├── index.html
        └── robots.txt
    ├── routers
        └── main.js
    ├── styles
        └── vendor
        │   ├── bootstrap.less
        │   ├── fontawesome.less
        │   ├── main.css
        │   ├── rickshaw.less
        │   └── select2.less
    ├── success.html
    ├── templates
        ├── admins.html
        ├── adminsList.html
        ├── adminsListItem.html
        ├── alert.html
        ├── dashboard.html
        ├── dashboardLog.html
        ├── dashboardLogItem.html
        ├── dashboardStatus.html
        ├── devicesList.html
        ├── devicesListItem.html
        ├── header.html
        ├── hostUsage.html
        ├── hostsList.html
        ├── hostsListItem.html
        ├── linkLocationsList.html
        ├── linkLocationsListItem.html
        ├── linksList.html
        ├── linksListItem.html
        ├── login.html
        ├── modal.html
        ├── modalAddAdmin.html
        ├── modalAddLink.html
        ├── modalAddLocHost.html
        ├── modalAddLocPeer.html
        ├── modalAddLocRoute.html
        ├── modalAddLocTransit.html
        ├── modalAddLocation.html
        ├── modalAddOrg.html
        ├── modalAddRoute.html
        ├── modalAddUser.html
        ├── modalAddUserBulk.html
        ├── modalAttachHost.html
        ├── modalAttachLink.html
        ├── modalAttachOrg.html
        ├── modalAuditUser.html
        ├── modalDeleteAdmins.html
        ├── modalDeleteHost.html
        ├── modalDeleteLink.html
        ├── modalDeleteLocHost.html
        ├── modalDeleteLocPeer.html
        ├── modalDeleteLocRoute.html
        ├── modalDeleteLocTransit.html
        ├── modalDeleteLocation.html
        ├── modalDeleteOrg.html
        ├── modalDeleteServer.html
        ├── modalDeleteUserDevice.html
        ├── modalDeleteUsers.html
        ├── modalDetachHost.html
        ├── modalDetachLink.html
        ├── modalDetachOrg.html
        ├── modalDeviceRegister.html
        ├── modalEmailUsers.html
        ├── modalEnterprise.html
        ├── modalHostSettings.html
        ├── modalKeyLink.html
        ├── modalLocHostConf.html
        ├── modalLocHostUri.html
        ├── modalModifyAdmin.html
        ├── modalModifyLink.html
        ├── modalModifyLocHost.html
        ├── modalModifyLocation.html
        ├── modalModifyRoute.html
        ├── modalNotification.html
        ├── modalOtpAuth.html
        ├── modalRekeyLink.html
        ├── modalRemoveRoute.html
        ├── modalRenameOrg.html
        ├── modalRenameUser.html
        ├── modalServerSettings.html
        ├── modalSettings.html
        ├── modalSubscribe.html
        ├── orgsList.html
        ├── orgsListItem.html
        ├── serverBandwidth.html
        ├── serverHostsList.html
        ├── serverHostsListItem.html
        ├── serverLinksList.html
        ├── serverLinksListItem.html
        ├── serverOrgsList.html
        ├── serverOrgsListItem.html
        ├── serverRoutesList.html
        ├── serverRoutesListItem.html
        ├── serversList.html
        ├── serversListItem.html
        ├── userDevicesList.html
        ├── userDevicesListItem.html
        ├── userServersList.html
        ├── userServersListItem.html
        ├── usersList.html
        └── usersListItem.html
    ├── upgrade.html
    ├── vendor
        ├── ace
        │   ├── ace.js
        │   ├── mode-log.js
        │   ├── mode-sh.js
        │   ├── mode-text.js
        │   ├── theme-chrome.js
        │   ├── theme-github.js
        │   └── theme-pritunl.js
        ├── backbone
        │   ├── backbone.js
        │   └── backbone.min.js
        ├── bootstrap
        │   ├── bootstrap.js
        │   └── bootstrap.min.js
        ├── d3
        │   ├── d3.js
        │   └── d3.min.js
        ├── dist
        │   ├── css
        │   │   └── main.ba2871d7609300bffd5be71db89cfb10.css
        │   ├── fonts
        │   │   ├── FontAwesome.otf
        │   │   ├── fontawesome-webfont.eot
        │   │   ├── fontawesome-webfont.svg
        │   │   ├── fontawesome-webfont.ttf
        │   │   ├── fontawesome-webfont.woff
        │   │   ├── fontawesome-webfont.woff2
        │   │   ├── fredoka-one.eot
        │   │   ├── fredoka-one.woff
        │   │   ├── glyphicons-halflings-regular.eot
        │   │   ├── glyphicons-halflings-regular.svg
        │   │   ├── glyphicons-halflings-regular.ttf
        │   │   ├── glyphicons-halflings-regular.woff
        │   │   ├── ubuntu-bold.eot
        │   │   ├── ubuntu-bold.woff
        │   │   ├── ubuntu.eot
        │   │   └── ubuntu.woff
        │   ├── index.html
        │   ├── js
        │   │   ├── main.85e69cf5c29607b79a29cc9a230bae78.js
        │   │   └── require.min.js
        │   └── robots.txt
        ├── jquery
        │   ├── jquery.js
        │   └── jquery.min.js
        ├── less
        │   ├── less.js
        │   └── less.min.js
        ├── qrcode
        │   ├── qrcode.js
        │   └── qrcode.min.js
        ├── require
        │   ├── require.js
        │   └── require.min.js
        ├── requireText
        │   └── text.js
        ├── rickshaw
        │   ├── rickshaw.js
        │   └── rickshaw.min.js
        ├── select
        │   ├── select.js
        │   └── select.min.js
        └── underscore
        │   ├── underscore.js
        │   └── underscore.min.js
    ├── views
        ├── admins.js
        ├── adminsList.js
        ├── adminsListItem.js
        ├── alert.js
        ├── dashboard.js
        ├── dashboardLog.js
        ├── dashboardLogItem.js
        ├── dashboardStatus.js
        ├── devices.js
        ├── devicesList.js
        ├── devicesListItem.js
        ├── header.js
        ├── hostUsage.js
        ├── hosts.js
        ├── hostsList.js
        ├── hostsListItem.js
        ├── linkLocationsList.js
        ├── linkLocationsListItem.js
        ├── links.js
        ├── linksList.js
        ├── linksListItem.js
        ├── list.js
        ├── login.js
        ├── loginBackdrop.js
        ├── logs.js
        ├── modal.js
        ├── modalAddAdmin.js
        ├── modalAddLink.js
        ├── modalAddLocHost.js
        ├── modalAddLocPeer.js
        ├── modalAddLocRoute.js
        ├── modalAddLocTransit.js
        ├── modalAddLocation.js
        ├── modalAddOrg.js
        ├── modalAddRoute.js
        ├── modalAddServer.js
        ├── modalAddUser.js
        ├── modalAddUserBulk.js
        ├── modalAttachHost.js
        ├── modalAttachLink.js
        ├── modalAttachOrg.js
        ├── modalAuditUser.js
        ├── modalDeleteAdmins.js
        ├── modalDeleteHost.js
        ├── modalDeleteLink.js
        ├── modalDeleteLocHost.js
        ├── modalDeleteLocPeer.js
        ├── modalDeleteLocRoute.js
        ├── modalDeleteLocTransit.js
        ├── modalDeleteLocation.js
        ├── modalDeleteOrg.js
        ├── modalDeleteServer.js
        ├── modalDeleteUserDevice.js
        ├── modalDeleteUsers.js
        ├── modalDetachHost.js
        ├── modalDetachLink.js
        ├── modalDetachOrg.js
        ├── modalDeviceRegister.js
        ├── modalEmailUsers.js
        ├── modalEnterprise.js
        ├── modalHostSettings.js
        ├── modalKeyLink.js
        ├── modalLocHostConf.js
        ├── modalLocHostUbntConf.js
        ├── modalLocHostUri.js
        ├── modalLogs.js
        ├── modalModifyAdmin.js
        ├── modalModifyLink.js
        ├── modalModifyLocHost.js
        ├── modalModifyLocation.js
        ├── modalModifyRoute.js
        ├── modalNotification.js
        ├── modalOtpAuth.js
        ├── modalRekeyLink.js
        ├── modalRemoveRoute.js
        ├── modalRenameOrg.js
        ├── modalRenameUser.js
        ├── modalServerSettings.js
        ├── modalSettings.js
        ├── modalSubscribe.js
        ├── orgsList.js
        ├── orgsListItem.js
        ├── serverBandwidth.js
        ├── serverHostsList.js
        ├── serverHostsListItem.js
        ├── serverLinksList.js
        ├── serverLinksListItem.js
        ├── serverOrgsList.js
        ├── serverOrgsListItem.js
        ├── serverOutput.js
        ├── serverOutputLink.js
        ├── serverRoutesList.js
        ├── serverRoutesListItem.js
        ├── servers.js
        ├── serversList.js
        ├── serversListItem.js
        ├── text.js
        ├── userDevicesList.js
        ├── userDevicesListItem.js
        ├── userServersList.js
        ├── userServersListItem.js
        ├── users.js
        ├── usersList.js
        └── usersListItem.js
    └── yubico.html


/.gitignore:
--------------------------------------------------------------------------------
 1 | .DS_Store
 2 | .DS_Store?
 3 | ._*
 4 | .Spotlight-V100
 5 | .Trashes
 6 | Icon?
 7 | ehthumbs.db
 8 | Thumbs.db
 9 | *.pyc
10 | *.egg
11 | *.egg-info
12 | *.tfstate
13 | *.tfstate.backup
14 | .sass-cache
15 | /.vagrant
16 | /build
17 | /dist
18 | /var
19 | /pritunl.egg-info
20 | /pritunl.db
21 | /www/node_modules
22 | /www/styles/*
23 | !/www/styles/vendor
24 | /tools/build_keys.json
25 | /tools/development_pritunl.conf
26 | 


--------------------------------------------------------------------------------
/data/etc/pritunl.conf:
--------------------------------------------------------------------------------
 1 | {
 2 |     "debug": false,
 3 |     "bind_addr": "0.0.0.0",
 4 |     "port": 443,
 5 |     "log_path": "/var/log/pritunl.log",
 6 |     "temp_path": "/tmp/pritunl_%r",
 7 |     "local_address_interface": "auto",
 8 |     "mongodb_uri": ""
 9 | }
10 | 


--------------------------------------------------------------------------------
/data/init.d.sysvinit/pritunl:
--------------------------------------------------------------------------------
 1 | #!/bin/sh
 2 | ### BEGIN INIT INFO
 3 | # Provides:          pritunl
 4 | # Required-Start:    $local_fs $network $named $time $syslog
 5 | # Required-Stop:     $local_fs $network $named $time $syslog
 6 | # Default-Start:     2 3 4 5
 7 | # Default-Stop:      0 1 6
 8 | # Description:       Pritunl Daemon
 9 | ### END INIT INFO
10 | 
11 | PIDFILE=/var/run/pritunl.pid
12 | 
13 | start() {
14 |   if [ -f $PIDFILE ] && kill -0 $(cat $PIDFILE); then
15 |     echo 'Service already running' >&2
16 |     return 1
17 |   fi
18 |   ulimit -n 50000
19 |   echo 'Starting service...' >&2
20 |   pritunl start --daemon --pidfile $PIDFILE > /dev/null
21 |   echo 'Service started' >&2
22 | }
23 | 
24 | stop() {
25 |   if [ ! -f "$PIDFILE" ] || ! kill -0 $(cat "$PIDFILE"); then
26 |     echo 'Service not running' >&2
27 |     return 1
28 |   fi
29 |   echo 'Stopping service...' >&2
30 |   kill -15 $(cat "$PIDFILE") && rm -f "$PIDFILE"
31 |   echo 'Service stopped' >&2
32 | }
33 | 
34 | case "$1" in
35 |   start)
36 |     start
37 |     ;;
38 |   stop)
39 |     stop
40 |     ;;
41 |   restart)
42 |     stop
43 |     start
44 |     ;;
45 |   *)
46 |     echo "Usage: $0 {start|stop|restart}"
47 | esac
48 | 


--------------------------------------------------------------------------------
/data/init/pritunl.conf:
--------------------------------------------------------------------------------
1 | description "Pritunl Daemon"
2 | limit nofile 50000 50000
3 | 
4 | start on runlevel [2345]
5 | stop on runlevel [!2345]
6 | 
7 | exec pritunl start
8 | 


--------------------------------------------------------------------------------
/data/systemd/pritunl-web.service:
--------------------------------------------------------------------------------
 1 | [Service]
 2 | User=pritunl-web
 3 | Group=pritunl-web
 4 | EnvironmentFile=/var/lib/pritunl/pritunl_web_env
 5 | ExecStart=/usr/bin/pritunl-web
 6 | TimeoutStopSec=5s
 7 | LimitNOFILE=500000
 8 | LimitNPROC=512
 9 | PrivateTmp=true
10 | ProtectSystem=full
11 | ProtectHostname=true
12 | ProtectKernelTunables=true
13 | AmbientCapabilities=CAP_NET_BIND_SERVICE
14 | 


--------------------------------------------------------------------------------
/data/systemd/pritunl.service:
--------------------------------------------------------------------------------
 1 | [Unit]
 2 | Description=Pritunl Daemon
 3 | 
 4 | [Service]
 5 | LimitNOFILE=500000
 6 | ExecStart=%PREFIX%/bin/pritunl start
 7 | SuccessExitStatus=SIGALRM
 8 | TimeoutStopSec=20
 9 | 
10 | [Install]
11 | WantedBy=multi-user.target
12 | 


--------------------------------------------------------------------------------
/data/var/pritunl.log:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/data/var/pritunl.log


--------------------------------------------------------------------------------
/data/var/pritunl.log.1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/data/var/pritunl.log.1


--------------------------------------------------------------------------------
/pritunl/__init__.py:
--------------------------------------------------------------------------------
 1 | from pritunl import patches
 2 | from pritunl.constants import *
 3 | 
 4 | __title__ = 'pritunl'
 5 | __version__ = '1.32.4278.46'
 6 | __author__ = 'Pritunl'
 7 | __email__ = 'contact@pritunl.com'
 8 | __license__ = 'Custom'
 9 | __copyright__ = 'Copyright 2013-2021 Pritunl <contact@pritunl.com>'
10 | conf_path = DEFAULT_CONF_PATH
11 | 
12 | def set_conf_path(path=None):
13 |     if path:
14 |         global conf_path
15 |         conf_path = path
16 | 
17 | def init_server():
18 |     from pritunl import app
19 |     from pritunl import setup
20 |     setup.setup_all()
21 |     app.run_server()
22 | 


--------------------------------------------------------------------------------
/pritunl/auth/__init__.py:
--------------------------------------------------------------------------------
1 | from pritunl.auth.administrator import *
2 | from pritunl.auth.app import *
3 | from pritunl.auth.csrf import *
4 | from pritunl.auth.utils import *
5 | 


--------------------------------------------------------------------------------
/pritunl/auth/app.py:
--------------------------------------------------------------------------------
 1 | from pritunl.auth.administrator import check_session
 2 | 
 3 | import flask
 4 | 
 5 | def session_auth(call):
 6 |     def _wrapped(*args, **kwargs):
 7 |         if not check_session(True):
 8 |             return flask.abort(401)
 9 |         flask.g.valid = True
10 |         return call(*args, **kwargs)
11 |     _wrapped.__name__ = '%s_session_auth' % call.__name__
12 |     return _wrapped
13 | 
14 | def session_light_auth(call):
15 |     def _wrapped(*args, **kwargs):
16 |         if not check_session(False):
17 |             return flask.abort(401)
18 |         flask.g.valid = True
19 |         return call(*args, **kwargs)
20 |     _wrapped.__name__ = '%s_session_light_auth' % call.__name__
21 |     return _wrapped
22 | 
23 | def open_auth(call):
24 |     def _wrapped(*args, **kwargs):
25 |         flask.g.valid = True
26 |         return call(*args, **kwargs)
27 |     _wrapped.__name__ = '%s_open_auth' % call.__name__
28 |     return _wrapped
29 | 


--------------------------------------------------------------------------------
/pritunl/auth/csrf.py:
--------------------------------------------------------------------------------
 1 | from pritunl import utils
 2 | from pritunl import mongo
 3 | 
 4 | def get_token(admin_id):
 5 |     coll = mongo.get_collection('auth_csrf_tokens')
 6 |     token = utils.generate_secret()
 7 | 
 8 |     coll.insert_one({
 9 |         '_id': token,
10 |         'admin_id': admin_id,
11 |         'timestamp': utils.now(),
12 |     })
13 | 
14 |     return token
15 | 
16 | def validate_token(admin_id, token):
17 |     coll = mongo.get_collection('auth_csrf_tokens')
18 | 
19 |     return bool(coll.find_one({
20 |         '_id': token,
21 |         'admin_id': admin_id,
22 |     }))
23 | 


--------------------------------------------------------------------------------
/pritunl/authorizer/__init__.py:
--------------------------------------------------------------------------------
1 | from pritunl.authorizer.authorizer import Authorizer
2 | 


--------------------------------------------------------------------------------
/pritunl/cachelocal/__init__.py:
--------------------------------------------------------------------------------
1 | from pritunl.cachelocal.cache_trie import *
2 | 
3 | from pritunl import tunldb
4 | 
5 | cache_db = tunldb.TunlDB(strict=False)
6 | 


--------------------------------------------------------------------------------
/pritunl/callbacks/__init__.py:
--------------------------------------------------------------------------------
1 | from pritunl.callbacks.callbacks import *
2 | 


--------------------------------------------------------------------------------
/pritunl/clients/__init__.py:
--------------------------------------------------------------------------------
1 | from pritunl.clients.clients import Clients
2 | 


--------------------------------------------------------------------------------
/pritunl/database/__init__.py:
--------------------------------------------------------------------------------
1 | from pritunl.database.utils import *
2 | 


--------------------------------------------------------------------------------
/pritunl/database/utils.py:
--------------------------------------------------------------------------------
 1 | from pritunl.constants import *
 2 | from pritunl import logger
 3 | 
 4 | import bson
 5 | import time
 6 | 
 7 | start = time.time()
 8 | 
 9 | def ObjectId(oid=None):
10 |     if oid is not None:
11 |         oid = str(oid)
12 |     if oid is None or len(oid) != 32:
13 |         try:
14 |             return bson.ObjectId(oid)
15 |         except:
16 |             logger.exception('Failed to convert object id', 'utils',
17 |                 object_id=oid,
18 |             )
19 |     return oid
20 | 
21 | def ObjectIdSilent(oid=None):
22 |     if oid is not None:
23 |         oid = str(oid)
24 |     if oid is None or len(oid) != 32:
25 |         return bson.ObjectId(oid)
26 |     return oid
27 | 
28 | def ParseObjectId(oid):
29 |     if oid:
30 |         return bson.ObjectId(str(oid))
31 | 


--------------------------------------------------------------------------------
/pritunl/firewall/__init__.py:
--------------------------------------------------------------------------------
1 | from pritunl.firewall.firewall import *
2 | 


--------------------------------------------------------------------------------
/pritunl/handlers/__init__.py:
--------------------------------------------------------------------------------
 1 | import pritunl.handlers.errors
 2 | import pritunl.handlers.auth
 3 | import pritunl.handlers.before_request
 4 | import pritunl.handlers.device
 5 | import pritunl.handlers.event
 6 | import pritunl.handlers.host
 7 | import pritunl.handlers.key
 8 | import pritunl.handlers.link
 9 | import pritunl.handlers.log
10 | import pritunl.handlers.logs
11 | import pritunl.handlers.org
12 | import pritunl.handlers.ping
13 | import pritunl.handlers.robots
14 | import pritunl.handlers.server
15 | import pritunl.handlers.settings
16 | import pritunl.handlers.static
17 | import pritunl.handlers.status
18 | import pritunl.handlers.sso
19 | import pritunl.handlers.subscription
20 | import pritunl.handlers.user
21 | import pritunl.handlers.admin
22 | 


--------------------------------------------------------------------------------
/pritunl/handlers/before_request.py:
--------------------------------------------------------------------------------
 1 | from pritunl.constants import *
 2 | from pritunl import settings
 3 | from pritunl import app
 4 | from pritunl import database
 5 | 
 6 | import flask
 7 | 
 8 | @app.app.before_request
 9 | def before_request():
10 |     if settings.local.www_state == DISABLED:
11 |         raise flask.abort(401, settings.local.notification)
12 | 
13 | @app.app.url_value_preprocessor
14 | def parse_object_id(_, values):
15 |     if values:
16 |         for key in values:
17 |             if key.endswith('_id'):
18 |                 val = values[key]
19 |                 if len(val) > 10:
20 |                     try:
21 |                         values[key] = database.ObjectIdSilent(val)
22 |                     except:
23 |                         values[key] = None
24 | 


--------------------------------------------------------------------------------
/pritunl/handlers/event.py:
--------------------------------------------------------------------------------
 1 | from pritunl.helpers import *
 2 | from pritunl import utils
 3 | from pritunl import event
 4 | from pritunl import app
 5 | from pritunl import auth
 6 | from pritunl import settings
 7 | from pritunl import database
 8 | 
 9 | import flask
10 | import time
11 | 
12 | @app.app.route('/event', methods=['GET'])
13 | @app.app.route('/event/<cursor>', methods=['GET'])
14 | @auth.session_auth
15 | def event_get(cursor=None):
16 |     if settings.app.demo_mode:
17 |         time.sleep(0.1)
18 |         return utils.jsonify([{
19 |             'id': 'demo',
20 |         }])
21 | 
22 |     if check_global_interrupt():
23 |         raise flask.abort(500)
24 | 
25 |     if cursor is not None:
26 |         cursor = database.ParseObjectId(cursor)
27 | 
28 |     return utils.jsonify(event.get_events(
29 |         cursor=cursor, yield_app_server=True))
30 | 


--------------------------------------------------------------------------------
/pritunl/handlers/log.py:
--------------------------------------------------------------------------------
 1 | from pritunl.constants import *
 2 | from pritunl import utils
 3 | from pritunl import app
 4 | from pritunl import auth
 5 | from pritunl import logger
 6 | from pritunl import settings
 7 | 
 8 | @app.app.route('/log', methods=['GET'])
 9 | @auth.session_auth
10 | def log_get():
11 |     if settings.app.demo_mode:
12 |         return utils.jsonify(DEMO_LOG_ENTRIES)
13 | 
14 |     log_entries = []
15 | 
16 |     for log_entry in logger.iter_log_entries():
17 |         log_entries.append(log_entry.dict())
18 | 
19 |     return utils.jsonify(log_entries)
20 | 


--------------------------------------------------------------------------------
/pritunl/handlers/logs.py:
--------------------------------------------------------------------------------
 1 | from pritunl.constants import *
 2 | 
 3 | from pritunl import app
 4 | from pritunl import logger
 5 | from pritunl import utils
 6 | from pritunl import auth
 7 | from pritunl import settings
 8 | 
 9 | @app.app.route('/logs', methods=['GET'])
10 | @auth.session_auth
11 | def logs_get():
12 |     if settings.app.demo_mode:
13 |         return utils.jsonify({
14 |             'output': DEMO_LOGS,
15 |         })
16 | 
17 |     log_view = logger.LogView()
18 |     return utils.jsonify({
19 |         'output': log_view.get_log_lines(
20 |             natural=True,
21 |             formatted=False,
22 |             reverse=True,
23 |         ).split('\n'),
24 |     })
25 | 


--------------------------------------------------------------------------------
/pritunl/handlers/ping.py:
--------------------------------------------------------------------------------
 1 | from pritunl import settings
 2 | from pritunl import utils
 3 | from pritunl import app
 4 | from pritunl import auth
 5 | 
 6 | import flask
 7 | import datetime
 8 | 
 9 | @app.app.route('/ping', methods=['GET'])
10 | @app.app.route('/check', methods=['GET'])
11 | @auth.open_auth
12 | def ping_get():
13 |     ping_timestamp = settings.local.host_ping_timestamp
14 |     host_ping_ttl = datetime.timedelta(seconds=settings.app.host_ping_ttl)
15 | 
16 |     if ping_timestamp and utils.now() > ping_timestamp + host_ping_ttl:
17 |         raise flask.abort(504)
18 |     else:
19 |         return utils.response(data='OK')
20 | 


--------------------------------------------------------------------------------
/pritunl/handlers/robots.py:
--------------------------------------------------------------------------------
 1 | from pritunl.constants import *
 2 | from pritunl import utils
 3 | from pritunl import app
 4 | from pritunl import auth
 5 | 
 6 | @app.app.route('/robots.txt', methods=['GET'])
 7 | @auth.open_auth
 8 | def robots_get():
 9 |     return utils.response(data=ROBOTS)
10 | 


--------------------------------------------------------------------------------
/pritunl/host/__init__.py:
--------------------------------------------------------------------------------
 1 | from pritunl.host.host import Host
 2 | from pritunl.host.usage import HostUsage
 3 | from pritunl.host.utils import *
 4 | 
 5 | from pritunl import docdb
 6 | 
 7 | global_clients = docdb.DocDb(
 8 |     'instance_id',
 9 |     'client_id',
10 | )
11 | 
12 | global_servers = set()
13 | dns_mapping_servers = set()
14 | 


--------------------------------------------------------------------------------
/pritunl/journal/__init__.py:
--------------------------------------------------------------------------------
 1 | from pritunl.journal.events import *
 2 | 
 3 | from pritunl.constants import *
 4 | from pritunl import settings
 5 | from pritunl import utils
 6 | 
 7 | import collections
 8 | import bson
 9 | 
10 | journal_queue = collections.deque()
11 | 
12 | def get_base_entry(event):
13 |     data = {
14 |         'id': bson.ObjectId(),
15 |         'event': event,
16 |         'timestamp': int(utils.time_now()),
17 |     }
18 | 
19 |     data.update(settings.local.host.journal_data)
20 | 
21 |     return data
22 | 
23 | def entry(event, *args, **kwargs):
24 |     if settings.app.auditing != ALL:
25 |         return
26 | 
27 |     event = get_base_entry(event)
28 |     for arg in args:
29 |         event.update(arg)
30 |     event.update(kwargs)
31 |     journal_queue.append(event)
32 | 


--------------------------------------------------------------------------------
/pritunl/link/__init__.py:
--------------------------------------------------------------------------------
1 | from pritunl.link.link import *
2 | from pritunl.link.utils import *
3 | 


--------------------------------------------------------------------------------
/pritunl/listener.py:
--------------------------------------------------------------------------------
1 | import collections
2 | 
3 | channels = collections.defaultdict(set)
4 | 
5 | def add_listener(channel, callback):
6 |     channels[channel].add(callback)
7 | 


--------------------------------------------------------------------------------
/pritunl/logger/filter.py:
--------------------------------------------------------------------------------
1 | import logging
2 | 
3 | class LogFilter(logging.Filter):
4 |     def filter(self, record):
5 |         return 1
6 | 


--------------------------------------------------------------------------------
/pritunl/mongo/__init__.py:
--------------------------------------------------------------------------------
 1 | from pritunl.mongo.dict import MongoDict
 2 | from pritunl.mongo.list import MongoList
 3 | from pritunl.mongo.object import MongoObject
 4 | 
 5 | database = None
 6 | secondary_database = None
 7 | prefix = ''
 8 | collection_types = {}
 9 | 
10 | def get_collection(name):
11 |     coll_type = collection_types.get(name)
12 |     if coll_type == 1:
13 |         coll = getattr(database, prefix + name)
14 |     elif coll_type == 2:
15 |         coll = getattr(secondary_database, prefix + name)
16 |     else:
17 |         raise TypeError('Invalid collection name')
18 | 
19 |     coll.name_str = name
20 |     return coll
21 | 


--------------------------------------------------------------------------------
/pritunl/monitoring/utils.py:
--------------------------------------------------------------------------------
 1 | import urllib.parse
 2 | 
 3 | def get_servers(uri):
 4 |     uri = urllib.parse.urlparse(uri)
 5 | 
 6 |     netloc = uri.netloc.split('@', 1)
 7 |     if len(netloc) == 2:
 8 |         username, password = netloc[0].split(':', 1)
 9 |         netloc = netloc[1]
10 |     else:
11 |         username = None
12 |         password = None
13 |         netloc = netloc[0]
14 | 
15 |     hosts = []
16 |     netloc = netloc.split(',')
17 |     for host in netloc:
18 |         host, port = host.split(':', 1)
19 |         try:
20 |             port = int(port)
21 |         except:
22 |             port = 0
23 | 
24 |         hosts.append((host, port))
25 | 
26 |     if uri.path:
27 |         database = uri.path.replace('/', '', 1)
28 |     else:
29 |         database = None
30 | 
31 |     return hosts, username, password, database
32 | 


--------------------------------------------------------------------------------
/pritunl/objcache.py:
--------------------------------------------------------------------------------
 1 | import threading
 2 | 
 3 | class ObjCache(object):
 4 |     def __init__(self, ttl=60):
 5 |         self._ttl = ttl
 6 |         self._data = {}
 7 |         self._timers = {}
 8 | 
 9 |     def remove(self, key):
10 |         self._data.pop(key, None)
11 | 
12 |     def set(self, key, val):
13 |         cur_timer = self._timers.pop(key, None)
14 |         if cur_timer:
15 |             cur_timer.cancel()
16 | 
17 |         timer = threading.Timer(self._ttl, self.remove, (key,))
18 |         timer.daemon = True
19 |         self._timers[key] = timer
20 |         timer.start()
21 | 
22 |         self._data[key] = val
23 | 
24 |     def get(self, key):
25 |         return self._data.get(key)
26 | 


--------------------------------------------------------------------------------
/pritunl/organization/__init__.py:
--------------------------------------------------------------------------------
1 | from pritunl.organization.organization import Organization
2 | from pritunl.organization.utils import *
3 | 


--------------------------------------------------------------------------------
/pritunl/patches.py:
--------------------------------------------------------------------------------
 1 | import requests
 2 | import os
 3 | 
 4 | os.environ['BOTO_CONFIG'] = ''
 5 | 
 6 | try:
 7 |     requests.packages.urllib3.disable_warnings()
 8 | except:
 9 |     pass
10 | 


--------------------------------------------------------------------------------
/pritunl/plugins/__init__.py:
--------------------------------------------------------------------------------
1 | from pritunl.plugins.plugins import *
2 | 


--------------------------------------------------------------------------------
/pritunl/plugins/utils.py:
--------------------------------------------------------------------------------
1 | import inspect
2 | 
3 | def get_functions(module):
4 |     funcs = {}
5 |     for x in inspect.getmembers(module):
6 |         if inspect.isfunction(x[1]):
7 |             funcs[x[0]] = x[1]
8 |     return funcs
9 | 


--------------------------------------------------------------------------------
/pritunl/pooler.py:
--------------------------------------------------------------------------------
 1 | pooler_types = {}
 2 | 
 3 | def add_pooler(fill_type):
 4 |     def add_pooler_wrap(func):
 5 |         pooler_types[fill_type] = func
 6 |         return func
 7 |     return add_pooler_wrap
 8 | 
 9 | def fill(fill_type, *args, **kwargs):
10 |     pooler_types[fill_type](*args, **kwargs)
11 | 


--------------------------------------------------------------------------------
/pritunl/poolers/__init__.py:
--------------------------------------------------------------------------------
1 | from pritunl.poolers import dh_params
2 | from pritunl.poolers import org
3 | from pritunl.poolers import user
4 | 


--------------------------------------------------------------------------------
/pritunl/poolers/org.py:
--------------------------------------------------------------------------------
 1 | from pritunl.constants import *
 2 | from pritunl import settings
 3 | from pritunl import pooler
 4 | from pritunl import mongo
 5 | from pritunl import organization
 6 | 
 7 | @pooler.add_pooler('org')
 8 | def fill_org():
 9 |     collection = mongo.get_collection('organizations')
10 |     queue_collection = mongo.get_collection('queue')
11 | 
12 |     org_pool_count = collection.count_documents({
13 |         'type': ORG_POOL,
14 |     })
15 | 
16 |     org_pool_count += queue_collection.count_documents({
17 |         'type': 'init_org_pooled',
18 |     })
19 | 
20 |     for _ in range(settings.app.org_pool_size - org_pool_count):
21 |         org = organization.new_org(type=ORG_POOL, block=False)
22 | 


--------------------------------------------------------------------------------
/pritunl/queue/__init__.py:
--------------------------------------------------------------------------------
1 | from pritunl.queue.com import QueueCom
2 | from pritunl.queue.queue import Queue
3 | from pritunl.queue.utils import *
4 | 


--------------------------------------------------------------------------------
/pritunl/queues/__init__.py:
--------------------------------------------------------------------------------
1 | from pritunl.queues.assign_ip_addr import QueueAssignIpAddr
2 | from pritunl.queues.assign_ip_pool import QueueAssignIpPool
3 | from pritunl.queues.dh_params import QueueDhParams
4 | from pritunl.queues.init_org_pooled import QueueInitOrgPooled
5 | from pritunl.queues.init_user import QueueInitUser
6 | from pritunl.queues.init_user_pooled import QueueInitUserPooled
7 | from pritunl.queues.unassign_ip_addr import QueueUnassignIpAddr
8 | 


--------------------------------------------------------------------------------
/pritunl/runners/firewall.py:
--------------------------------------------------------------------------------
 1 | from pritunl.constants import *
 2 | from pritunl.helpers import *
 3 | from pritunl import logger
 4 | from pritunl import settings
 5 | from pritunl import firewall
 6 | 
 7 | import threading
 8 | import time
 9 | 
10 | @interrupter
11 | def _keep_alive_thread():
12 |     while True:
13 |         try:
14 |             time.sleep(1)
15 |             firewall.update()
16 |         except:
17 |             logger.exception('Error in firewall update', 'runners',
18 |                 host_id=settings.local.host_id,
19 |                 host_name=settings.local.host.name,
20 |             )
21 |             time.sleep(0.5)
22 | 
23 | def start_firewall():
24 |     threading.Thread(name="FirewallKeepAlive",
25 |         target=_keep_alive_thread).start()
26 | 


--------------------------------------------------------------------------------
/pritunl/runners/instance.py:
--------------------------------------------------------------------------------
1 | from pritunl import server
2 | from pritunl import listener
3 | 
4 | def start_instance():
5 |     listener.add_listener('instance', server.on_msg)
6 | 


--------------------------------------------------------------------------------
/pritunl/runners/limiter.py:
--------------------------------------------------------------------------------
 1 | from pritunl.helpers import *
 2 | from pritunl import logger
 3 | from pritunl import settings
 4 | from pritunl import limiter
 5 | 
 6 | import time
 7 | import threading
 8 | 
 9 | @interrupter
10 | def _limiter_runner_thread():
11 |     while True:
12 |         try:
13 |             for limtr in limiter.limiters:
14 |                 cur_time = time.time()
15 |                 for peer, (expire, count) in list(limtr.peers_expire_count.items()):
16 |                     if cur_time > expire:
17 |                         limtr.peers_expire_count.pop(peer, None)
18 | 
19 |             yield interrupter_sleep(settings.app.peer_limit_timeout * 2)
20 | 
21 |         except GeneratorExit:
22 |             raise
23 |         except:
24 |             logger.exception('Error in limiter runner thread', 'runners')
25 |             time.sleep(0.5)
26 | 
27 | def start_limiter():
28 |     threading.Thread(name="LimiterRunner",
29 |         target=_limiter_runner_thread).start()
30 | 


--------------------------------------------------------------------------------
/pritunl/runners/server.py:
--------------------------------------------------------------------------------
 1 | from pritunl import settings
 2 | from pritunl import logger
 3 | from pritunl import server
 4 | from pritunl import listener
 5 | 
 6 | import time
 7 | 
 8 | def _on_msg(msg):
 9 |     if msg['message'] != 'start':
10 |         return
11 | 
12 |     try:
13 |         svr = server.get_by_id(msg['server_id'])
14 |         if settings.local.host_id not in svr.hosts:
15 |             return
16 | 
17 |         for instance in svr.instances:
18 |             if instance['host_id'] == settings.local.host_id:
19 |                 return
20 | 
21 |         prefered_hosts = msg.get('prefered_hosts')
22 | 
23 |         if prefered_hosts and settings.local.host_id not in prefered_hosts:
24 |             time.sleep(0.1)
25 | 
26 |         svr.run(send_events=msg.get('send_events'))
27 |     except:
28 |         logger.exception('Failed to run server', 'runners')
29 | 
30 | def start_server():
31 |     listener.add_listener('servers', _on_msg)
32 | 


--------------------------------------------------------------------------------
/pritunl/runners/settings.py:
--------------------------------------------------------------------------------
 1 | from pritunl.helpers import *
 2 | from pritunl import settings
 3 | from pritunl import listener
 4 | from pritunl import logger
 5 | 
 6 | import threading
 7 | 
 8 | @interrupter
 9 | def _check():
10 |     yield
11 | 
12 |     try:
13 |         settings.reload_mongo()
14 |     except:
15 |         logger.exception('Settings check failed', 'runners')
16 | 
17 |     _start_check_timer()
18 | 
19 | def _start_check_timer():
20 |     thread = threading.Timer(settings.app.settings_check_interval, _check)
21 |     thread.daemon = True
22 |     thread.start()
23 | 
24 | def start_settings():
25 |     listener.add_listener('setting', settings.on_msg)
26 |     _start_check_timer()
27 | 


--------------------------------------------------------------------------------
/pritunl/runners/subscription.py:
--------------------------------------------------------------------------------
 1 | from pritunl.constants import *
 2 | from pritunl.helpers import *
 3 | from pritunl import settings
 4 | from pritunl import subscription
 5 | from pritunl import logger
 6 | 
 7 | import threading
 8 | 
 9 | @interrupter
10 | def _subscription_thread():
11 |     while True:
12 |         try:
13 |             yield interrupter_sleep(SUBSCRIPTION_UPDATE_RATE)
14 |             subscription.update()
15 |         except GeneratorExit:
16 |             raise
17 |         except:
18 |             logger.exception('Error in subscription thread', 'runners')
19 | 
20 | def start_subscription():
21 |     settings.local.sub_active = None
22 |     subscription.update()
23 |     threading.Thread(name="SubRunner", target=_subscription_thread).start()
24 | 


--------------------------------------------------------------------------------
/pritunl/runners/time_sync.py:
--------------------------------------------------------------------------------
 1 | from pritunl.helpers import *
 2 | from pritunl import utils
 3 | from pritunl import logger
 4 | 
 5 | import threading
 6 | 
 7 | @interrupter
 8 | def _time_sync_thread():
 9 |     while True:
10 |         try:
11 |             utils.sync_time()
12 |         except:
13 |             logger.exception('Failed to sync time', 'runners')
14 |             yield interrupter_sleep(300)
15 |             continue
16 |         yield interrupter_sleep(1800)
17 | 
18 | def start_time_sync():
19 |     threading.Thread(name="TimeSync", target=_time_sync_thread).start()
20 | 


--------------------------------------------------------------------------------
/pritunl/runners/tokens.py:
--------------------------------------------------------------------------------
 1 | from pritunl.helpers import *
 2 | from pritunl import logger
 3 | from pritunl import sso
 4 | 
 5 | import threading
 6 | import time
 7 | 
 8 | @interrupter
 9 | def tokens_thread():
10 |     while True:
11 |         try:
12 |             time.sleep(3)
13 |             sso.sync_tokens()
14 |         except GeneratorExit:
15 |             raise
16 |         except:
17 |             logger.exception('Error in token sync thread', 'runners')
18 |             time.sleep(1)
19 | 
20 |         yield
21 | 
22 | def start_tokens():
23 |     threading.Thread(name="TokensRunner", target=tokens_thread).start()
24 | 


--------------------------------------------------------------------------------
/pritunl/runners/update_server.py:
--------------------------------------------------------------------------------
 1 | from pritunl.helpers import *
 2 | from pritunl import app
 3 | 
 4 | import threading
 5 | 
 6 | @interrupter
 7 | def _update_server_thread():
 8 |     while True:
 9 |         app.update_server()
10 |         yield interrupter_sleep(3)
11 | 
12 | def start_update_server():
13 |     threading.Thread(name="UpdateServer", target=_update_server_thread).start()
14 | 


--------------------------------------------------------------------------------
/pritunl/server/__init__.py:
--------------------------------------------------------------------------------
1 | from pritunl.server.server import Server, dict_fields, operation_fields
2 | from pritunl.server.instance import get_instance
3 | from pritunl.server.bandwidth import ServerBandwidth
4 | from pritunl.server.listener import on_msg
5 | from pritunl.server.ip_pool import *
6 | from pritunl.server.utils import *
7 | 


--------------------------------------------------------------------------------
/pritunl/server/listener.py:
--------------------------------------------------------------------------------
 1 | _channels = {}
 2 | 
 3 | def add_listener(instance_id, callback):
 4 |     _channels[instance_id] = callback
 5 | 
 6 | def remove_listener(instance_id):
 7 |     _channels.pop(instance_id, None)
 8 | 
 9 | def on_msg(msg):
10 |     for callback in list(_channels.values()):
11 |         callback(msg)
12 | 


--------------------------------------------------------------------------------
/pritunl/settings/__init__.py:
--------------------------------------------------------------------------------
 1 | from pritunl.settings.settings import Settings
 2 | 
 3 | from pritunl.settings.app import SettingsApp
 4 | from pritunl.settings.conf import SettingsConf
 5 | from pritunl.settings.local import SettingsLocal
 6 | from pritunl.settings.mongo import SettingsMongo
 7 | from pritunl.settings.user import SettingsUser
 8 | from pritunl.settings.vpn import SettingsVpn
 9 | 
10 | import sys
11 | 
12 | app = SettingsApp
13 | conf = SettingsConf
14 | local = SettingsLocal
15 | mongo = SettingsMongo
16 | user = SettingsUser
17 | vpn = SettingsVpn
18 | 
19 | def commit():
20 |     pass
21 | 
22 | sys.modules[__name__] = Settings()
23 | 


--------------------------------------------------------------------------------
/pritunl/settings/group_base.py:
--------------------------------------------------------------------------------
 1 | class SettingsGroupBase(object):
 2 |     group = None
 3 |     fields = {}
 4 | 
 5 |     def __getattr__(self, name):
 6 |         if name in self.fields:
 7 |             return self.fields[name]
 8 |         raise AttributeError('%s instance has no attribute %r' % (
 9 |             self.__class__.__name__, name))
10 | 


--------------------------------------------------------------------------------
/pritunl/settings/group_file.py:
--------------------------------------------------------------------------------
 1 | from pritunl.settings.group_base import SettingsGroupBase
 2 | 
 3 | from pritunl.constants import *
 4 | 
 5 | import json
 6 | import os
 7 | 
 8 | class SettingsGroupFile(SettingsGroupBase):
 9 |     type = GROUP_FILE
10 |     path = None
11 |     commit_fields = set()
12 | 
13 |     def load(self):
14 |         if not os.path.isfile(self.path):
15 |             return
16 | 
17 |         os.chmod(self.path, 0o600)
18 |         with open(self.path, 'r') as settings_file:
19 |             doc = json.loads(settings_file.read())
20 | 
21 |         for field, value in list(doc.items()):
22 |             setattr(self, field, value)
23 | 
24 |     def commit(self):
25 |         doc = {}
26 | 
27 |         for field, default in self.fields.items():
28 |             if hasattr(self, field):
29 |                 value = getattr(self, field)
30 |                 if field in self.commit_fields or value != default:
31 |                     doc[field] = getattr(self, field)
32 | 
33 |         with open(self.path, 'w') as settings_file:
34 |             os.chmod(self.path, 0o600)
35 |             settings_file.write(json.dumps(doc, indent=4))
36 | 


--------------------------------------------------------------------------------
/pritunl/settings/group_local.py:
--------------------------------------------------------------------------------
1 | from pritunl.settings.group_base import SettingsGroupBase
2 | 
3 | from pritunl.constants import *
4 | 
5 | class SettingsGroupLocal(SettingsGroupBase):
6 |     type = GROUP_LOCAL
7 | 


--------------------------------------------------------------------------------
/pritunl/settings/local.py:
--------------------------------------------------------------------------------
 1 | from pritunl.settings.group_local import SettingsGroupLocal
 2 | 
 3 | import threading
 4 | 
 5 | server_start = threading.Event()
 6 | server_start.set()
 7 | 
 8 | class SettingsLocal(SettingsGroupLocal):
 9 |     group = 'local'
10 |     fields = {
11 |         'se_host_key': None,
12 |         'se_authorize_key': None,
13 |         'se_encryption_key': None,
14 |         'se_client_key': None,
15 |         'se_client_pub_key': None,
16 |         'quiet': False,
17 |         'public_ip': None,
18 |         'public_ip6': None,
19 |         'server_ready': threading.Event(),
20 |         'server_start': server_start,
21 |         'host_ping_timestamp': None,
22 |         'ntp_time': None,
23 |         'sub_active': False,
24 |         'sub_status': None,
25 |         'sub_plan': None,
26 |         'sub_amount': None,
27 |         'sub_period_end': None,
28 |         'sub_trial_end': None,
29 |         'sub_cancel_at_period_end': None,
30 |         'sub_balance': None,
31 |         'sub_premium_buy_url': False,
32 |         'sub_enterprise_buy_url': False,
33 |         'sub_portal_url': False,
34 |         'sub_url_key': False,
35 |         'sub_styles': {},
36 |     }
37 | 


--------------------------------------------------------------------------------
/pritunl/settings/mongo.py:
--------------------------------------------------------------------------------
 1 | from pritunl.settings.group_mongo import SettingsGroupMongo
 2 | 
 3 | class SettingsMongo(SettingsGroupMongo):
 4 |     group = 'mongo'
 5 |     fields = {
 6 |         'tran_max_attempts': 6,
 7 |         'tran_ttl': 10,
 8 |         'queue_max_attempts': 3,
 9 |         'queue_ttl': 15,
10 |         'task_max_attempts': 3,
11 |         'task_ttl': 30,
12 |     }
13 | 


--------------------------------------------------------------------------------
/pritunl/settings/user.py:
--------------------------------------------------------------------------------
 1 | from pritunl.constants import *
 2 | from pritunl.settings.group_mongo import SettingsGroupMongo
 3 | 
 4 | class SettingsUser(SettingsGroupMongo):
 5 |     group = 'user'
 6 |     fields = {
 7 |         'audit_limit': 2500,
 8 |         'gravatar': True,
 9 |         'otp_secret_len': 16,
10 |         'pin_mode': PIN_OPTIONAL,
11 |         'pin_min_length': 6,
12 |         'pin_digits_only': True,
13 |         'device_key_override': None,
14 |         'device_key_length': 4,
15 |         'device_reg_attempts': 10,
16 |         'reconnect': True,
17 |         'password_encryption': True,
18 |         'cert_key_bits': 4096,
19 |         'cert_message_digest': 'sha256',
20 |         'page_count': 10,
21 |         'skip_remote_sso_check': False,
22 |         'conf_sync': True,
23 |         'restrict_import': False,
24 |         'restrict_client': False,
25 |     }
26 | 


--------------------------------------------------------------------------------
/pritunl/setup/boto_conf.py:
--------------------------------------------------------------------------------
 1 | from pritunl import settings
 2 | 
 3 | import boto3
 4 | 
 5 | def setup_boto_conf():
 6 |     pass
 7 |     # TODO
 8 |     # boto.config.add_section('Boto')
 9 |     # boto.config.set('Boto', 'num_retries', '2')
10 |     # boto.config.set('Boto', 'http_socket_timeout',
11 |     #     str(int(settings.app.aws_timeout)))
12 | 


--------------------------------------------------------------------------------
/pritunl/setup/cache.py:
--------------------------------------------------------------------------------
1 | from pritunl import cache
2 | 
3 | def setup_cache():
4 |     cache.init()
5 | 


--------------------------------------------------------------------------------
/pritunl/setup/check.py:
--------------------------------------------------------------------------------
 1 | from pritunl import logger
 2 | 
 3 | import pymongo
 4 | import bson
 5 | 
 6 | def setup_check():
 7 |     if not pymongo.has_c():
 8 |         logger.warning('Failed to load pymongo c bindings')
 9 | 
10 |     if not bson.has_c():
11 |         logger.warning('Failed to load bson c bindings')
12 | 


--------------------------------------------------------------------------------
/pritunl/setup/handlers.py:
--------------------------------------------------------------------------------
1 | def setup_handlers():
2 |     from pritunl import handlers
3 | 


--------------------------------------------------------------------------------
/pritunl/setup/host.py:
--------------------------------------------------------------------------------
 1 | from pritunl import mongo
 2 | from pritunl import listener
 3 | from pritunl import settings
 4 | 
 5 | def _on_msg(msg):
 6 |     if msg['message'] != 'updated':
 7 |         return
 8 |     settings.local.host.load()
 9 | 
10 | def setup_host():
11 |     from pritunl import host
12 |     collection = mongo.get_collection('settings')
13 | 
14 |     collection.update_one({
15 |         '_id': 'subscription',
16 |     }, {'$setOnInsert': {
17 |         'active': None,
18 |         'plan': None,
19 |     }}, upsert=True)
20 | 
21 |     host.init()
22 | 
23 |     listener.add_listener('hosts', _on_msg)
24 | 


--------------------------------------------------------------------------------
/pritunl/setup/host_fix.py:
--------------------------------------------------------------------------------
 1 | from pritunl import settings
 2 | from pritunl import subscription
 3 | 
 4 | def setup_host_fix():
 5 |     subscription.update()
 6 | 
 7 |     if settings.app.license and settings.app.license_plan != 'premium':
 8 |         return
 9 | 
10 |     from pritunl import server
11 |     host_id = settings.local.host_id
12 | 
13 |     for svr in server.iter_servers(fields=['hosts']):
14 |         if svr.hosts != [host_id]:
15 |             svr.hosts = [host_id]
16 |             svr.commit('hosts')
17 | 


--------------------------------------------------------------------------------
/pritunl/setup/logger.py:
--------------------------------------------------------------------------------
 1 | import logging
 2 | 
 3 | def setup_logger():
 4 |     from pritunl.app import app
 5 |     from pritunl import logger
 6 | 
 7 |     logger.log_handler = logger.LogHandler()
 8 | 
 9 |     logger.log_filter = logger.LogFilter()
10 |     logger.logger.addFilter(logger.log_filter)
11 | 
12 |     logger.logger.setLevel(logging.DEBUG)
13 |     logger.log_handler.setLevel(logging.DEBUG)
14 | 
15 |     logger.log_handler.setFormatter(logger.LogFormatter(
16 |         '[%(asctime)s][%(levelname)s] %(message)s'))
17 | 
18 |     logger.logger.addHandler(logger.log_handler)
19 | 
20 |     app.logger.setLevel(logging.DEBUG)
21 |     app.logger.addFilter(logger.log_filter)
22 |     app.logger.addHandler(logger.log_handler)
23 | 


--------------------------------------------------------------------------------
/pritunl/setup/monitoring.py:
--------------------------------------------------------------------------------
 1 | from pritunl.helpers import *
 2 | from pritunl import settings
 3 | from pritunl import logger
 4 | from pritunl import monitoring
 5 | 
 6 | import threading
 7 | 
 8 | @interrupter
 9 | def _monitoring_thread():
10 |     while True:
11 |         yield interrupter_sleep(settings.app.influxdb_interval)
12 |         try:
13 |             monitoring.connect()
14 |         except:
15 |             logger.exception('InfluxDB connection error',
16 |                 'monitoring',
17 |                 influxdb_uri=settings.app.influxdb_uri,
18 |             )
19 |             yield interrupter_sleep(5)
20 |             continue
21 | 
22 |         try:
23 |             monitoring.write_queue()
24 |         except:
25 |             logger.exception('InfluxDB write queue error',
26 |                 'monitoring',
27 |                 influxdb_uri=settings.app.influxdb_uri,
28 |             )
29 |             yield interrupter_sleep(5)
30 | 
31 | def setup_monitoring():
32 |     monitoring.init()
33 |     thread = threading.Thread(name="SetupMonitoring",
34 |         target=_monitoring_thread)
35 |     thread.daemon = True
36 |     thread.start()
37 | 


--------------------------------------------------------------------------------
/pritunl/setup/plugins.py:
--------------------------------------------------------------------------------
1 | from pritunl import plugins
2 | 
3 | def setup_plugins():
4 |     plugins.init()
5 | 


--------------------------------------------------------------------------------
/pritunl/setup/poolers.py:
--------------------------------------------------------------------------------
1 | def setup_poolers():
2 |     from pritunl import poolers
3 | 


--------------------------------------------------------------------------------
/pritunl/setup/public_ip.py:
--------------------------------------------------------------------------------
 1 | from pritunl import settings
 2 | from pritunl import utils
 3 | 
 4 | import threading
 5 | 
 6 | def setup_public_ip():
 7 |     utils.sync_public_ip()
 8 |     if not settings.local.public_ip:
 9 |         thread = threading.Thread(name="SetupPublicIp",
10 |             target=utils.sync_public_ip,
11 |             kwargs={'attempts': 5})
12 |         thread.daemon = True
13 |         thread.start()
14 | 


--------------------------------------------------------------------------------
/pritunl/setup/runners.py:
--------------------------------------------------------------------------------
1 | def setup_runners():
2 |     from pritunl import runners
3 |     runners.start_all()
4 | 


--------------------------------------------------------------------------------
/pritunl/setup/server_fix.py:
--------------------------------------------------------------------------------
1 | from pritunl import mongo
2 | 
3 | def setup_server_fix():
4 |     servers_collection = mongo.get_collection('servers')
5 | 
6 |     servers_collection.update_one({}, {'$set': {
7 |         'pool_cursor': None,
8 |     }})
9 | 


--------------------------------------------------------------------------------
/pritunl/setup/server_listeners.py:
--------------------------------------------------------------------------------
 1 | from pritunl import listener
 2 | from pritunl import callbacks
 3 | 
 4 | def setup_server_listeners():
 5 |     from pritunl import vxlan
 6 |     listener.add_listener('port_forwarding', callbacks.on_port_forwarding)
 7 |     listener.add_listener('client', callbacks.on_client)
 8 |     listener.add_listener('client_links', callbacks.on_client_link)
 9 |     listener.add_listener('vxlan', vxlan.on_vxlan)
10 | 


--------------------------------------------------------------------------------
/pritunl/setup/settings.py:
--------------------------------------------------------------------------------
 1 | from pritunl.helpers import *
 2 | from pritunl import settings
 3 | from pritunl import utils
 4 | 
 5 | def setup_settings():
 6 |     if not settings.app.oracle_private_key or \
 7 |             not settings.app.oracle_public_key:
 8 |         private_key, public_key = utils.generate_rsa_key()
 9 |         settings.app.oracle_private_key = private_key
10 |         settings.app.oracle_public_key = public_key
11 |         settings.commit()
12 | 


--------------------------------------------------------------------------------
/pritunl/setup/signal_handler.py:
--------------------------------------------------------------------------------
 1 | from pritunl.helpers import *
 2 | 
 3 | import signal
 4 | 
 5 | def handle_exit(signum, frame):
 6 |     set_global_interrupt()
 7 | 
 8 | def setup_signal_handler():
 9 |     signal.signal(signal.SIGINT, handle_exit)
10 |     signal.signal(signal.SIGTERM, handle_exit)
11 | 


--------------------------------------------------------------------------------
/pritunl/setup/subscription.py:
--------------------------------------------------------------------------------
 1 | from pritunl import listener
 2 | from pritunl import subscription
 3 | 
 4 | def _on_msg(msg):
 5 |     if msg['message'] != 'updated':
 6 |         return
 7 |     subscription.update()
 8 | 
 9 | def setup_subscription():
10 |     listener.add_listener('subscription', _on_msg)
11 | 


--------------------------------------------------------------------------------
/pritunl/setup/temp_path.py:
--------------------------------------------------------------------------------
 1 | from pritunl import settings
 2 | 
 3 | import os
 4 | import uuid
 5 | 
 6 | def setup_temp_path():
 7 |     settings.conf.temp_path = settings.conf.temp_path.replace(
 8 |         '%r', uuid.uuid4().hex)
 9 |     if not os.path.isdir(settings.conf.temp_path):
10 |         os.makedirs(settings.conf.temp_path)
11 | 


--------------------------------------------------------------------------------
/pritunl/setup/token.py:
--------------------------------------------------------------------------------
1 | from pritunl import sso
2 | 
3 | def setup_token():
4 |     sso.init_token()
5 | 


--------------------------------------------------------------------------------
/pritunl/sso/__init__.py:
--------------------------------------------------------------------------------
 1 | from pritunl.sso.duo import Duo
 2 | from pritunl.sso.yubico import auth_yubico
 3 | from pritunl.sso.azure import verify_azure
 4 | from pritunl.sso.authzero import verify_authzero
 5 | from pritunl.sso.google import verify_google
 6 | from pritunl.sso.jumpcloud import auth_jumpcloud
 7 | from pritunl.sso.radius import verify_radius
 8 | from pritunl.sso.okta import auth_okta, auth_okta_secondary
 9 | from pritunl.sso.onelogin import auth_onelogin, auth_onelogin_secondary
10 | from pritunl.sso.token import *
11 | from pritunl.sso.utils import *
12 | 


--------------------------------------------------------------------------------
/pritunl/static/__init__.py:
--------------------------------------------------------------------------------
1 | from pritunl.static.static import *
2 | from pritunl.static.utils import *
3 | 


--------------------------------------------------------------------------------
/pritunl/static/utils.py:
--------------------------------------------------------------------------------
 1 | import sys
 2 | import zlib
 3 | import time
 4 | 
 5 | def generate_etag(file_name, file_size, mtime):
 6 |     file_name = file_name.encode(sys.getfilesystemencoding())
 7 |     return 'wzsdm-%d-%s-%s' % (
 8 |         time.mktime(mtime.timetuple()),
 9 |         file_size,
10 |         zlib.adler32(file_name) & 0xffffffff,
11 |     )
12 | 


--------------------------------------------------------------------------------
/pritunl/system/__init__.py:
--------------------------------------------------------------------------------
1 | from pritunl.system.sysctl import *
2 | 


--------------------------------------------------------------------------------
/pritunl/system/sysctl.py:
--------------------------------------------------------------------------------
 1 | from pritunl.constants import *
 2 | from pritunl.exceptions import *
 3 | from pritunl import utils
 4 | from pritunl import logger
 5 | 
 6 | import subprocess
 7 | 
 8 | def sysctl_upsert(key, value, required=True):
 9 |     try:
10 |         output = utils.check_output_logged(['sysctl', key])
11 |     except subprocess.CalledProcessError:
12 |         logger.exception('Failed to read sysctl value',
13 |             'server', key=key, value=value,
14 |         )
15 |         output = ''
16 | 
17 |     for line in output.split('\n'):
18 |         if ('%s =' % key) in line:
19 |             if line.split('=')[-1].strip() == value:
20 |                 return
21 | 
22 |     try:
23 |         utils.check_output_logged(
24 |             ['sysctl', '-w', '%s=%s' % (key, value)])
25 |     except subprocess.CalledProcessError:
26 |         logger.exception('Failed to update sysctl value', 'server',
27 |             key=key, value=value,
28 |         )
29 |         if required:
30 |             raise
31 | 


--------------------------------------------------------------------------------
/pritunl/tasks/__init__.py:
--------------------------------------------------------------------------------
 1 | import pritunl.tasks.acme_update
 2 | import pritunl.tasks.clean_ip_pool
 3 | import pritunl.tasks.clean_client_pool
 4 | import pritunl.tasks.clean_users
 5 | import pritunl.tasks.clean_network_links
 6 | import pritunl.tasks.clean_network_lock
 7 | import pritunl.tasks.pooler
 8 | import pritunl.tasks.route
 9 | import pritunl.tasks.sync_ip_pool
10 | import pritunl.tasks.server
11 | import pritunl.tasks.host
12 | import pritunl.tasks.link
13 | import pritunl.tasks.clean_servers
14 | import pritunl.tasks.clean_vxlans
15 | 


--------------------------------------------------------------------------------
/pritunl/tasks/acme_update.py:
--------------------------------------------------------------------------------
 1 | from pritunl import task
 2 | from pritunl import logger
 3 | from pritunl import acme
 4 | from pritunl import app
 5 | from pritunl import utils
 6 | from pritunl import settings
 7 | 
 8 | class AcmeUpdate(task.Task):
 9 |     type = 'acme_update'
10 | 
11 |     def task(self):
12 |         acme_domain = settings.app.acme_domain
13 | 
14 |         if not acme_domain:
15 |             return
16 | 
17 |         if settings.app.acme_timestamp and \
18 |             settings.app.acme_key and \
19 |                 utils.time_now() - settings.app.acme_timestamp < \
20 |                     settings.app.acme_renew:
21 |             return
22 | 
23 |         logger.info(
24 |             'Updating acme certificate', 'tasks',
25 |             acme_domain=acme_domain,
26 |         )
27 | 
28 |         acme.update_acme_cert()
29 |         app.update_server()
30 | 
31 | task.add_task(AcmeUpdate, hours=4, minutes=35, run_on_start=True)
32 | 


--------------------------------------------------------------------------------
/pritunl/tasks/clean_network_links.py:
--------------------------------------------------------------------------------
 1 | from pritunl.helpers import *
 2 | from pritunl import mongo
 3 | from pritunl import task
 4 | 
 5 | class TaskCleanNetworkLinks(task.Task):
 6 |     type = 'clean_network_links'
 7 | 
 8 |     @cached_static_property
 9 |     def user_collection(cls):
10 |         return mongo.get_collection('users')
11 | 
12 |     @cached_static_property
13 |     def user_net_link_collection(cls):
14 |         return mongo.get_collection('users_net_link')
15 | 
16 |     def task(self):
17 |         user_ids_link = set(self.user_net_link_collection.find({}, {
18 |             '_id': True,
19 |             'user_id': True,
20 |         }).distinct('user_id'))
21 | 
22 |         user_ids = set(self.user_collection.find({}, {
23 |             '_id': True,
24 |         }).distinct('_id'))
25 | 
26 |         self.user_net_link_collection.delete_many({
27 |             'user_id': {'$in': list(user_ids_link - user_ids)},
28 |         })
29 | 
30 | task.add_task(TaskCleanNetworkLinks, hours=5, minutes=47)
31 | 


--------------------------------------------------------------------------------
/pritunl/tasks/clean_network_lock.py:
--------------------------------------------------------------------------------
 1 | from pritunl.helpers import *
 2 | from pritunl import mongo
 3 | from pritunl import task
 4 | from pritunl import utils
 5 | 
 6 | class TaskCleanNetworkLock(task.Task):
 7 |     type = 'clean_network_lock'
 8 | 
 9 |     @cached_static_property
10 |     def server_collection(cls):
11 |         return mongo.get_collection('servers')
12 | 
13 |     def task(self):
14 |         self.server_collection.update_many({
15 |             'network_lock_ttl': {'$lt': utils.now()},
16 |         }, {'$unset': {
17 |             'network_lock': '',
18 |             'network_lock_ttl': '',
19 |         }})
20 | 
21 | task.add_task(TaskCleanNetworkLock,
22 |     minutes=range(0, 60, 8), run_on_start=True)
23 | 


--------------------------------------------------------------------------------
/pritunl/tasks/clean_vxlans.py:
--------------------------------------------------------------------------------
 1 | from pritunl.helpers import *
 2 | from pritunl import mongo
 3 | from pritunl import task
 4 | 
 5 | class TaskCleanVxlans(task.Task):
 6 |     type = 'clean_vxlan'
 7 | 
 8 |     @cached_static_property
 9 |     def server_collection(cls):
10 |         return mongo.get_collection('servers')
11 | 
12 |     @cached_static_property
13 |     def vxlan_collection(cls):
14 |         return mongo.get_collection('vxlans')
15 | 
16 |     def task(self):
17 |         server_ids = set(self.server_collection.find().distinct('_id'))
18 |         vxlan_ids = set(self.vxlan_collection.find().distinct('server_id'))
19 | 
20 |         self.vxlan_collection.delete_many({
21 |             'server_id': {'$in': list(vxlan_ids - server_ids)}
22 |         })
23 | 
24 | task.add_task(TaskCleanVxlans, minutes=52)
25 | 


--------------------------------------------------------------------------------
/pritunl/tasks/link.py:
--------------------------------------------------------------------------------
 1 | from pritunl import settings
 2 | from pritunl import task
 3 | from pritunl import link
 4 | 
 5 | import collections
 6 | 
 7 | class TaskLink(task.Task):
 8 |     type = 'link'
 9 |     delay = 10
10 | 
11 |     def task(self):
12 |         if settings.app.demo_mode:
13 |             return
14 | 
15 |         hosts = []
16 |         location_available_hosts = collections.defaultdict(list)
17 |         for hst in link.iter_hosts():
18 |             hosts.append(hst)
19 | 
20 |             if not hst.is_available:
21 |                 continue
22 | 
23 |             location_available_hosts[hst.location_id].append(hst)
24 | 
25 |         for hst in hosts:
26 |             hst.update_available(location_available_hosts[hst.location_id])
27 | 
28 | task.add_task(TaskLink, seconds=range(0, 60, 3))
29 | 


--------------------------------------------------------------------------------
/pritunl/tasks/pooler.py:
--------------------------------------------------------------------------------
 1 | from pritunl import pooler
 2 | from pritunl import task
 3 | 
 4 | class TaskPooler(task.Task):
 5 |     type = 'pooler'
 6 | 
 7 |     def task(self):
 8 |         pooler.fill('org')
 9 |         pooler.fill('user')
10 |         pooler.fill('dh_params')
11 | 
12 | task.add_task(TaskPooler, minutes=range(0, 60, 5))
13 | 


--------------------------------------------------------------------------------
/pritunl/tasks/sync_ip_pool.py:
--------------------------------------------------------------------------------
 1 | from pritunl import task
 2 | from pritunl import logger
 3 | from pritunl import server
 4 | 
 5 | class TaskSyncIpPool(task.Task):
 6 |     type = 'sync_ip_pool'
 7 | 
 8 |     def task(self):
 9 |         for svr in server.iter_servers():
10 |             try:
11 |                 svr.ip_pool.sync_ip_pool()
12 |             except:
13 |                 logger.exception('Failed to sync server IP pool', 'tasks',
14 |                     server_id=svr.id,
15 |                     task_id=self.id,
16 |                 )
17 | 
18 | task.add_task(TaskSyncIpPool, hours=4, minutes=7)
19 | 


--------------------------------------------------------------------------------
/pritunl/transaction/__init__.py:
--------------------------------------------------------------------------------
1 | from pritunl.transaction.transaction import Transaction
2 | from pritunl.transaction.collection import TransactionCollection
3 | 


--------------------------------------------------------------------------------
/pritunl/transaction/action.py:
--------------------------------------------------------------------------------
 1 | from pritunl.constants import *
 2 | 
 3 | class TransactionAction:
 4 |     def __init__(self, actions, func):
 5 |         self._actions = actions
 6 |         self._func = func
 7 | 
 8 |     def __call__(self, *args, **kwargs):
 9 |         from pritunl.transaction.collection import TransactionCollection
10 |         self._actions.append([
11 |             self._func,
12 |             args or '',
13 |             kwargs or '',
14 |         ])
15 |         return TransactionCollection(self._actions)
16 | 
17 |     def __getattr__(self, name):
18 |         if name in MONGO_ACTION_METHODS:
19 |             return TransactionAction(self._actions, name)
20 |         raise AttributeError(
21 |             'TransactionAction instance has no attribute %r' % name)
22 | 


--------------------------------------------------------------------------------
/pritunl/upgrade/upgrade_1_17.py:
--------------------------------------------------------------------------------
1 | from pritunl.upgrade.utils import get_collection
2 | 
3 | def upgrade_1_17():
4 |     hosts_collection = get_collection('hosts')
5 |     hosts_collection.update_many({}, {'$set': {
6 |         'local_address': None,
7 |     }})
8 | 


--------------------------------------------------------------------------------
/pritunl/upgrade/upgrade_1_18.py:
--------------------------------------------------------------------------------
 1 | from pritunl.upgrade.utils import get_collection
 2 | 
 3 | def upgrade_1_18():
 4 |     servers_collection = get_collection('servers')
 5 |     settings_collection = get_collection('settings')
 6 | 
 7 |     nat = True
 8 |     doc = settings_collection.find_one({'_id': 'vpn'})
 9 |     if doc:
10 |         nat = doc.get('nat_routes', True)
11 | 
12 |     for doc in servers_collection.find({}):
13 |         routes = []
14 | 
15 |         if doc.get('mode') == 'all_traffic':
16 |             routes.append({
17 |                 'network': '0.0.0.0/0',
18 |                 'nat': nat,
19 |             })
20 | 
21 |         for local_network in doc.get('local_networks', []):
22 |             routes.append({
23 |                 'network': local_network,
24 |                 'nat': nat,
25 |             })
26 | 
27 |         servers_collection.update_one({
28 |             '_id': doc['_id'],
29 |         }, {'$set': {
30 |             'routes': routes,
31 |         }})
32 | 


--------------------------------------------------------------------------------
/pritunl/upgrade/upgrade_1_4.py:
--------------------------------------------------------------------------------
 1 | from pritunl.upgrade.utils import get_collection
 2 | 
 3 | from pritunl import utils
 4 | 
 5 | def upgrade_1_4():
 6 |     ip_pool_collection = get_collection('servers_ip_pool')
 7 | 
 8 |     docs = ip_pool_collection.find({}, {
 9 |         '_id': True,
10 |         'network': True,
11 |     })
12 | 
13 |     for doc in docs:
14 |         if not doc.get('network'):
15 |             continue
16 | 
17 |         if isinstance(doc['network'], int):
18 |             continue
19 | 
20 |         ip_pool_collection.update_one({
21 |             '_id': doc['_id'],
22 |         }, {'$set': {
23 |             'network': utils.fnv32a(doc['network'])
24 |         }})
25 | 


--------------------------------------------------------------------------------
/pritunl/upgrade/upgrade_1_5.py:
--------------------------------------------------------------------------------
 1 | from pritunl.upgrade.utils import get_collection
 2 | 
 3 | def upgrade_1_5():
 4 |     settings_collection = get_collection('settings')
 5 | 
 6 |     response = settings_collection.update_one({
 7 |         '_id': 'app',
 8 |         'sso': True,
 9 |     }, {'$set': {
10 |         'sso': 'google',
11 |     }})
12 | 
13 |     if not bool(response.modified_count):
14 |         settings_collection.update_one({
15 |             '_id': 'app',
16 |         }, {'$set': {
17 |             'sso': None,
18 |         }})
19 | 


--------------------------------------------------------------------------------
/pritunl/user/__init__.py:
--------------------------------------------------------------------------------
1 | from pritunl.user.user import User
2 | from pritunl.user.utils import *
3 | 


--------------------------------------------------------------------------------
/pritunl/utils/__init__.py:
--------------------------------------------------------------------------------
 1 | from pritunl.utils.cert import *
 2 | from pritunl.utils.filter import *
 3 | from pritunl.utils.json_helpers import *
 4 | from pritunl.utils.least_common_counter import *
 5 | from pritunl.utils.mail import *
 6 | from pritunl.utils.misc import *
 7 | from pritunl.utils.proc import *
 8 | from pritunl.utils.network import *
 9 | from pritunl.utils.aws import *
10 | from pritunl.utils.oracle import *
11 | from pritunl.utils.sig import *
12 | from pritunl.utils.none_queue import NoneQueue
13 | from pritunl.utils.auth import *
14 | from pritunl.utils.md5_hash import unsafe_md5
15 | 


--------------------------------------------------------------------------------
/pritunl/utils/auth.py:
--------------------------------------------------------------------------------
 1 | from pritunl import settings
 2 | 
 3 | def get_onelogin_mode():
 4 |     if settings.app.sso_onelogin_mode is not None:
 5 |         return settings.app.sso_onelogin_mode
 6 |     if settings.app.sso_onelogin_push:
 7 |         if settings.app.sso_onelogin_skip_unavailable:
 8 |             return 'push_none'
 9 |         return 'push'
10 |     return ''
11 | 
12 | def get_okta_mode():
13 |     if settings.app.sso_okta_mode is not None:
14 |         return settings.app.sso_okta_mode
15 |     if settings.app.sso_okta_push:
16 |         if settings.app.sso_okta_skip_unavailable:
17 |             return 'push_none'
18 |         return 'push'
19 |     return ''
20 | 


--------------------------------------------------------------------------------
/pritunl/utils/least_common_counter.py:
--------------------------------------------------------------------------------
 1 | import collections
 2 | import heapq
 3 | import operator
 4 | 
 5 | class LeastCommonCounter(collections.Counter):
 6 |     def least_common(self, n=None):
 7 |         if n is None:
 8 |             return sorted(iter(self.items()), key=operator.itemgetter(1))
 9 |         return heapq.nsmallest(n, iter(self.items()), key=operator.itemgetter(1))
10 | 


--------------------------------------------------------------------------------
/pritunl/utils/sig.py:
--------------------------------------------------------------------------------
 1 | from pritunl.utils.filter import session_str
 2 | from pritunl.utils.misc import const_compare
 3 | from pritunl import settings
 4 | 
 5 | import base64
 6 | import hashlib
 7 | import hmac
 8 | import flask
 9 | 
10 | def get_sig(sig_str, secret):
11 |     return base64.b64encode(
12 |         hmac.new(secret.encode(), sig_str.encode(), hashlib.sha512).digest(),
13 |     ).decode()
14 | 
15 | def get_flask_sig():
16 |     sig_str = '&'.join((
17 |         session_str('session_id'),
18 |         session_str('admin_id'),
19 |         session_str('timestamp'),
20 |     ))
21 |     return get_sig(
22 |         settings.app.cookie_secret2,
23 |         sig_str,
24 |     )
25 | 
26 | def set_flask_sig():
27 |     flask.session['signature'] = get_flask_sig()
28 | 
29 | def check_flask_sig():
30 |     return const_compare(session_str('signature'), get_flask_sig())
31 | 


--------------------------------------------------------------------------------
/pritunl/vault/__init__.py:
--------------------------------------------------------------------------------
1 | from pritunl.vault.vault import *
2 | from pritunl.vault.batch import *
3 | from pritunl.vault.item import *
4 | from pritunl.vault.utils import *
5 | 


--------------------------------------------------------------------------------
/pritunl/vault/nonces.py:
--------------------------------------------------------------------------------
1 | _nonces = set()
2 | 
3 | def nonces_add(nonce):
4 |     _nonces.add(nonce)
5 | 
6 | def nonces_contains(nonce):
7 |     return nonce in _nonces
8 | 


--------------------------------------------------------------------------------
/pritunl/vxlan/__init__.py:
--------------------------------------------------------------------------------
1 | from pritunl.vxlan.vxlan import *
2 | 


--------------------------------------------------------------------------------
/selinux/pritunl_dns.fc:
--------------------------------------------------------------------------------
1 | /usr/bin/pritunl-dns -- gen_context(system_u:object_r:pritunl_dns_exec_t,s0)
2 | 


--------------------------------------------------------------------------------
/selinux/pritunl_web.fc:
--------------------------------------------------------------------------------
1 | /etc/systemd/system/pritunl-web.service -- gen_context(system_u:object_r:pritunl_web_unit_file_t,s0)
2 | /usr/lib/systemd/system/pritunl-web.service -- gen_context(system_u:object_r:pritunl_web_unit_file_t,s0)
3 | /usr/bin/pritunl-web -- gen_context(system_u:object_r:pritunl_web_exec_t,s0)
4 | 


--------------------------------------------------------------------------------
/selinux8/pritunl_dns.fc:
--------------------------------------------------------------------------------
1 | /usr/bin/pritunl-dns -- gen_context(system_u:object_r:pritunl_dns_exec_t,s0)
2 | 


--------------------------------------------------------------------------------
/selinux8/pritunl_web.fc:
--------------------------------------------------------------------------------
1 | /etc/systemd/system/pritunl-web.service -- gen_context(system_u:object_r:pritunl_web_unit_file_t,s0)
2 | /usr/lib/systemd/system/pritunl-web.service -- gen_context(system_u:object_r:pritunl_web_unit_file_t,s0)
3 | /usr/bin/pritunl-web -- gen_context(system_u:object_r:pritunl_web_exec_t,s0)
4 | 


--------------------------------------------------------------------------------
/selinux9/pritunl_dns.fc:
--------------------------------------------------------------------------------
1 | /usr/bin/pritunl-dns -- gen_context(system_u:object_r:pritunl_dns_exec_t,s0)
2 | 


--------------------------------------------------------------------------------
/selinux9/pritunl_web.fc:
--------------------------------------------------------------------------------
1 | /etc/systemd/system/pritunl-web.service -- gen_context(system_u:object_r:pritunl_web_unit_file_t,s0)
2 | /usr/lib/systemd/system/pritunl-web.service -- gen_context(system_u:object_r:pritunl_web_unit_file_t,s0)
3 | /usr/bin/pritunl-web -- gen_context(system_u:object_r:pritunl_web_exec_t,s0)
4 | 


--------------------------------------------------------------------------------
/server.py:
--------------------------------------------------------------------------------
1 | import pritunl.__main__
2 | 
3 | pritunl.__main__.main('/etc/pritunl.conf')
4 | 


--------------------------------------------------------------------------------
/tools/ami_init.sh:
--------------------------------------------------------------------------------
 1 | #!/bin/bash
 2 | echo -e "[pritunl]\nname=Pritunl Repository\nbaseurl=http://repo.pritunl.com/stable/yum/centos/7/\ngpgcheck=1\nenabled=1" > /etc/yum.repos.d/pritunl.repo
 3 | echo -e "description \"Pritunl Override\"\n\nstart on starting pritunl\nstop on runlevel [!2345]\n\npre-start script\n  stop pritunl\n  sleep 1\nend script" > /etc/init/pritunl-override.conf
 4 | echo -e "\nyum -y clean all\nyum -y upgrade\nsleep 1\nstart pritunl" >> /etc/rc.local
 5 | gpg --keyserver hkp://keyserver.ubuntu.com --recv-keys 7568D9BB55FF9E5287D586017AE645C0CF8E292A
 6 | gpg --armor --export 7568D9BB55FF9E5287D586017AE645C0CF8E292A > key.tmp
 7 | rpm --import key.tmp
 8 | rm -f key.tmp
 9 | yum -y upgrade
10 | yum -y install pritunl
11 | 


--------------------------------------------------------------------------------
/tools/ami_mongo_init.sh:
--------------------------------------------------------------------------------
 1 | #!/bin/bash
 2 | echo -e "[mongodb-org-3.4]\nname=MongoDB Repository\nbaseurl=https://repo.mongodb.org/yum/redhat/amazon/mongodb-org/3.4/x86_64/\ngpgcheck=1\nenabled=1\ngpgkey=https://www.mongodb.org/static/pgp/server-3.4.asc" > /etc/yum.repos.d/mongodb-org-3.4.repo
 3 | echo -e "[pritunl]\nname=Pritunl Repository\nbaseurl=http://repo.pritunl.com/stable/yum/centos/7/\ngpgcheck=1\nenabled=1" > /etc/yum.repos.d/pritunl.repo
 4 | echo -e "description \"Pritunl Override\"\n\nstart on starting pritunl\nstop on runlevel [!2345]\n\npre-start script\n  stop pritunl\n  sleep 1\nend script" > /etc/init/pritunl-override.conf
 5 | echo -e "\nyum -y clean all\nyum -y upgrade\nsleep 1\nstart pritunl" >> /etc/rc.local
 6 | gpg --keyserver hkp://keyserver.ubuntu.com --recv-keys 7568D9BB55FF9E5287D586017AE645C0CF8E292A
 7 | gpg --armor --export 7568D9BB55FF9E5287D586017AE645C0CF8E292A > key.tmp
 8 | rpm --import key.tmp
 9 | rm -f key.tmp
10 | yum -y upgrade
11 | yum -y install pritunl mongodb-org
12 | 


--------------------------------------------------------------------------------
/tools/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -e
3 | python2 tools/builder.py set-version $1
4 | python2 tools/builder.py build
5 | python2 tools/builder.py upload
6 | 


--------------------------------------------------------------------------------
/tools/development_pritunl.conf:
--------------------------------------------------------------------------------
1 | {
2 |     "static_cache": false,
3 |     "bind_addr": "0.0.0.0",
4 |     "log_path": "var/pritunl.log",
5 |     "www_path": "www",
6 |     "local_address_interface": "auto",
7 |     "mongodb_uri": "mongodb://localhost:27017/pritunl"
8 | }
9 | 


--------------------------------------------------------------------------------
/tools/stress_testing/connect_all.go:
--------------------------------------------------------------------------------
 1 | package main
 2 | 
 3 | import (
 4 | 	"fmt"
 5 | 	"os/exec"
 6 | 	"os"
 7 | 	"os/signal"
 8 | 	"syscall"
 9 | 	"time"
10 | )
11 | 
12 | const count = 256
13 | 
14 | func Exec(name string, args ...string) (cmd *exec.Cmd, err error) {
15 | 	cmd = exec.Command(name, args...)
16 | 	err = cmd.Start()
17 | 
18 | 	return
19 | }
20 | 
21 | func main() {
22 | 	cmds := []*exec.Cmd{}
23 | 
24 | 	defer func() {
25 | 		for _, cmd := range cmds {
26 | 			cmd.Process.Signal(os.Interrupt)
27 | 		}
28 | 		for _, cmd := range cmds {
29 | 			cmd.Wait()
30 | 		}
31 | 	}()
32 | 
33 | 	for i := 1; i <= count; i++ {
34 | 		cmd, err := Exec(
35 | 			"openvpn", fmt.Sprintf("user_%05d.ovpn", i),
36 | 		)
37 | 		if err != nil {
38 | 			panic(err)
39 | 		}
40 | 		cmds = append(cmds, cmd)
41 | 
42 | 		time.Sleep(100 * time.Millisecond)
43 | 	}
44 | 
45 | 	fmt.Println("\n")
46 | 
47 | 	signals := make(chan os.Signal, 1)
48 | 	signal.Notify(signals, os.Interrupt)
49 | 	signal.Notify(signals, syscall.SIGTERM)
50 | 	<-signals
51 | }
52 | 


--------------------------------------------------------------------------------
/tools/stress_testing/get_test_names.py:
--------------------------------------------------------------------------------
1 | COUNT = 60000
2 | 
3 | for i in xrange(1, COUNT + 1):
4 |     print 'user_%s' % str(i).zfill(5)
5 | 


--------------------------------------------------------------------------------
/tools/stress_testing/test_client/Dockerfile:
--------------------------------------------------------------------------------
 1 | FROM pritunl/archlinux
 2 | MAINTAINER Pritunl <contact@pritunl.com>
 3 | 
 4 | RUN pacman -S --noconfirm go git bzr openvpn net-tools wget
 5 | 
 6 | ENV GOPATH /go
 7 | ENV PATH $PATH:/go/bin
 8 | RUN go get github.com/gin-gonic/gin
 9 | 
10 | ADD . /test_client
11 | WORKDIR /test_client
12 | 
13 | ENTRYPOINT ["go", "run", "client.go"]
14 | 


--------------------------------------------------------------------------------
/tools/vagrant_provision.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | ntpdate ntp.ubuntu.com
3 | apt-get update -qq
4 | apt-get install -qq -y net-tools openvpn python python-dev python-pip bridge-utils
5 | pip install flask pymongo
6 | 


--------------------------------------------------------------------------------
/www/collections/admin.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone',
 5 |   'models/admin'
 6 | ], function($, _, Backbone, AdminModel) {
 7 |   'use strict';
 8 |   var AdminCollection = Backbone.Collection.extend({
 9 |     model: AdminModel,
10 |     url: function() {
11 |       return '/admin';
12 |     }
13 |   });
14 | 
15 |   return AdminCollection;
16 | });
17 | 


--------------------------------------------------------------------------------
/www/collections/adminAudit.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone',
 5 |   'models/userAudit'
 6 | ], function($, _, Backbone, UserAuditModel) {
 7 |   'use strict';
 8 |   var AdminAuditCollection = Backbone.Collection.extend({
 9 |     model: UserAuditModel,
10 |     initialize: function(options) {
11 |       this.user = options.user;
12 |     },
13 |     url: function() {
14 |       return '/admin/' + this.user.get('id') + '/audit';
15 |     }
16 |   });
17 | 
18 |   return AdminAuditCollection;
19 | });
20 | 


--------------------------------------------------------------------------------
/www/collections/device.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone',
 5 |   'models/device'
 6 | ], function($, _, Backbone, DeviceModel) {
 7 |   'use strict';
 8 |   var DeviceCollection = Backbone.Collection.extend({
 9 |     model: DeviceModel,
10 |     initialize: function() {
11 |     },
12 |     url: function() {
13 |       return '/device/unregistered';
14 |     },
15 |     parse: function(response) {
16 |       return response;
17 |     }
18 |   });
19 | 
20 |   return DeviceCollection;
21 | });
22 | 


--------------------------------------------------------------------------------
/www/collections/linkLocation.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone',
 5 |   'models/linkLocation'
 6 | ], function($, _, Backbone, LinkLocationModel) {
 7 |   'use strict';
 8 |   var LinkLocationCollection = Backbone.Collection.extend({
 9 |     model: LinkLocationModel,
10 |     initialize: function(options) {
11 |       this.link = options.link;
12 |     },
13 |     url: function() {
14 |       return '/link/' + this.link + '/location';
15 |     }
16 |   });
17 | 
18 |   return LinkLocationCollection;
19 | });
20 | 


--------------------------------------------------------------------------------
/www/collections/log.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone',
 5 |   'models/log'
 6 | ], function($, _, Backbone, LogModel) {
 7 |   'use strict';
 8 |   var LogCollection = Backbone.Collection.extend({
 9 |     model: LogModel,
10 |     url: function() {
11 |       return '/log';
12 |     }
13 |   });
14 | 
15 |   return LogCollection;
16 | });
17 | 


--------------------------------------------------------------------------------
/www/collections/serverHost.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone',
 5 |   'models/serverHost'
 6 | ], function($, _, Backbone, ServerHostModel) {
 7 |   'use strict';
 8 |   var ServerHostCollection = Backbone.Collection.extend({
 9 |     model: ServerHostModel,
10 |     initialize: function(options) {
11 |       this.server = options.server;
12 |     },
13 |     url: function() {
14 |       return '/server/' + this.server + '/host';
15 |     }
16 |   });
17 | 
18 |   return ServerHostCollection;
19 | });
20 | 


--------------------------------------------------------------------------------
/www/collections/serverLink.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone',
 5 |   'models/serverLink'
 6 | ], function($, _, Backbone, ServerLinkModel) {
 7 |   'use strict';
 8 |   var ServerLinkCollection = Backbone.Collection.extend({
 9 |     model: ServerLinkModel,
10 |     initialize: function(options) {
11 |       this.server = options.server;
12 |     },
13 |     url: function() {
14 |       return '/server/' + this.server + '/link';
15 |     }
16 |   });
17 | 
18 |   return ServerLinkCollection;
19 | });
20 | 


--------------------------------------------------------------------------------
/www/collections/serverOrg.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone',
 5 |   'models/serverOrg'
 6 | ], function($, _, Backbone, ServerOrgModel) {
 7 |   'use strict';
 8 |   var ServerOrgCollection = Backbone.Collection.extend({
 9 |     model: ServerOrgModel,
10 |     initialize: function(options) {
11 |       this.server = options.server;
12 |     },
13 |     url: function() {
14 |       return '/server/' + this.server + '/organization';
15 |     }
16 |   });
17 | 
18 |   return ServerOrgCollection;
19 | });
20 | 


--------------------------------------------------------------------------------
/www/collections/serverRoute.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone',
 5 |   'models/serverRoute'
 6 | ], function($, _, Backbone, ServerRouteModel) {
 7 |   'use strict';
 8 |   var ServerRouteCollection = Backbone.Collection.extend({
 9 |     model: ServerRouteModel,
10 |     initialize: function(options) {
11 |       this.server = options.server;
12 |     },
13 |     url: function() {
14 |       return '/server/' + this.server + '/route';
15 |     }
16 |   });
17 | 
18 |   return ServerRouteCollection;
19 | });
20 | 


--------------------------------------------------------------------------------
/www/collections/userAudit.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone',
 5 |   'models/userAudit'
 6 | ], function($, _, Backbone, UserAuditModel) {
 7 |   'use strict';
 8 |   var UserAuditCollection = Backbone.Collection.extend({
 9 |     model: UserAuditModel,
10 |     initialize: function(options) {
11 |       this.user = options.user;
12 |     },
13 |     url: function() {
14 |       return '/user/' + this.user.get('organization') + '/' +
15 |         this.user.get('id') + '/audit';
16 |     }
17 |   });
18 | 
19 |   return UserAuditCollection;
20 | });
21 | 


--------------------------------------------------------------------------------
/www/collections/userDevice.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone',
 5 |   'models/userDevice'
 6 | ], function($, _, Backbone, UserDeviceModel) {
 7 |   'use strict';
 8 |   var UserDeviceCollection = Backbone.Collection.extend({
 9 |     model: UserDeviceModel
10 |   });
11 | 
12 |   return UserDeviceCollection;
13 | });
14 | 


--------------------------------------------------------------------------------
/www/collections/userServer.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone',
 5 |   'models/userServer'
 6 | ], function($, _, Backbone, UserServerModel) {
 7 |   'use strict';
 8 |   var UserServerCollection = Backbone.Collection.extend({
 9 |     model: UserServerModel
10 |   });
11 | 
12 |   return UserServerCollection;
13 | });
14 | 


--------------------------------------------------------------------------------
/www/dart/lib/alert.dart:
--------------------------------------------------------------------------------
 1 | library alert;
 2 | 
 3 | import 'dart:collection' as collection;
 4 | 
 5 | collection.Queue<Alert> alerts = new collection.Queue();
 6 | 
 7 | class Alert {
 8 |   String type;
 9 |   String text;
10 | 
11 |   Alert(this.text, this.type) {
12 |     alerts.add(this);
13 | 
14 |     while (alerts.length > 3) {
15 |       alerts.removeFirst();
16 |     }
17 |   }
18 | }
19 | 
20 | void clear() {
21 |   alerts.clear();
22 | }
23 | 


--------------------------------------------------------------------------------
/www/dart/lib/all_aware.dart:
--------------------------------------------------------------------------------
 1 | library all_aware;
 2 | 
 3 | import 'package:angular/angular.dart' as ng;
 4 | import 'dart:html' as dom;
 5 | 
 6 | class AllAware implements ng.ShadowRootAware, ng.AttachAware {
 7 |   var _root;
 8 |   var _onAll;
 9 | 
10 |   void attach() {
11 |     if (this._onAll == true || this._root == null) {
12 |       return;
13 |     }
14 |     this._onAll = true;
15 |     this.onAll(this._root);
16 |   }
17 | 
18 |   void onShadowRoot(dom.ShadowRoot root) {
19 |     this._root = root;
20 |     if (this._onAll == true) {
21 |       return;
22 |     }
23 |     this._onAll = true;
24 |     this.onAll(this._root);
25 |   }
26 | 
27 |   void onAll(dom.ShadowRoot root) {}
28 | }
29 | 


--------------------------------------------------------------------------------
/www/dart/lib/collections/collections.dart:
--------------------------------------------------------------------------------
 1 | library collections;
 2 | 
 3 | import 'package:pritunl/collections/events.dart' as evnts;
 4 | import 'package:pritunl/collections/log_entries.dart' as log_ents;
 5 | import 'package:pritunl/collections/organizations.dart' as organizations;
 6 | import 'package:pritunl/collections/server_hosts.dart' as svr_hsts;
 7 | import 'package:pritunl/collections/server_orgs.dart' as svr_orgs;
 8 | import 'package:pritunl/collections/servers.dart' as svrs;
 9 | import 'package:pritunl/collections/users.dart' as usrs;
10 | 
11 | import 'package:angular/angular.dart' as ng;
12 | 
13 | class CollectionsMod extends ng.Module {
14 |   CollectionsMod() {
15 |     this.bind(evnts.Events);
16 |     this.bind(log_ents.LogEntries);
17 |     this.bind(organizations.Organizations);
18 |     this.bind(svr_hsts.ServerHosts);
19 |     this.bind(svr_orgs.ServerOrgs);
20 |     this.bind(svrs.Servers);
21 |     this.bind(usrs.Users);
22 |   }
23 | }
24 | 


--------------------------------------------------------------------------------
/www/dart/lib/collections/log_entries.dart:
--------------------------------------------------------------------------------
 1 | library log_entries_col;
 2 | 
 3 | import 'package:pritunl/collection.dart' as collec;
 4 | import 'package:pritunl/models/log_entry.dart' as log_ent;
 5 | 
 6 | import 'package:angular/angular.dart' show Injectable;
 7 | import 'package:angular/angular.dart' as ng;
 8 | 
 9 | @Injectable()
10 | class LogEntries extends collec.Collection {
11 |   Type model = log_ent.LogEntry;
12 | 
13 |   LogEntries(ng.Http http) : super(http);
14 | 
15 |   String get url {
16 |     return '/log';
17 |   }
18 | }
19 | 


--------------------------------------------------------------------------------
/www/dart/lib/collections/organizations.dart:
--------------------------------------------------------------------------------
 1 | library organizations_col;
 2 | 
 3 | import 'package:pritunl/collection.dart' as collec;
 4 | import 'package:pritunl/models/organization.dart' as organization;
 5 | 
 6 | import 'package:angular/angular.dart' show Injectable;
 7 | import 'package:angular/angular.dart' as ng;
 8 | 
 9 | @Injectable()
10 | class Organizations extends collec.Collection {
11 |   Type model = organization.Organization;
12 | 
13 |   Organizations(ng.Http http) : super(http);
14 | 
15 |   String get url {
16 |     return '/organization';
17 |   }
18 | }
19 | 


--------------------------------------------------------------------------------
/www/dart/lib/collections/server_hosts.dart:
--------------------------------------------------------------------------------
 1 | library server_hosts_col;
 2 | 
 3 | import 'package:pritunl/collection.dart' as collec;
 4 | import 'package:pritunl/models/server.dart' as svr;
 5 | import 'package:pritunl/models/server_host.dart' as svr_hst;
 6 | 
 7 | import 'package:angular/angular.dart' show Injectable;
 8 | import 'package:angular/angular.dart' as ng;
 9 | 
10 | @Injectable()
11 | class ServerHosts extends collec.Collection {
12 |   Type model = svr_hst.ServerHost;
13 |   svr.Server server;
14 | 
15 |   ServerHosts(ng.Http http, this.server) : super(http);
16 | 
17 |   String get url {
18 |     return '/server/${this.server.id}/host';
19 |   }
20 | }
21 | 


--------------------------------------------------------------------------------
/www/dart/lib/collections/server_orgs.dart:
--------------------------------------------------------------------------------
 1 | library server_orgs_col;
 2 | 
 3 | import 'package:pritunl/collection.dart' as collec;
 4 | import 'package:pritunl/models/server.dart' as svr;
 5 | import 'package:pritunl/models/server_org.dart' as svr_org;
 6 | 
 7 | import 'package:angular/angular.dart' show Injectable;
 8 | import 'package:angular/angular.dart' as ng;
 9 | 
10 | @Injectable()
11 | class ServerOrgs extends collec.Collection {
12 |   Type model = svr_org.ServerOrg;
13 |   svr.Server server;
14 | 
15 |   ServerOrgs(ng.Http http, this.server) : super(http);
16 | 
17 |   String get url {
18 |     return '/server/${this.server.id}/organization';
19 |   }
20 | }
21 | 


--------------------------------------------------------------------------------
/www/dart/lib/collections/servers.dart:
--------------------------------------------------------------------------------
 1 | library server_col;
 2 | 
 3 | import 'package:pritunl/collection.dart' as collec;
 4 | import 'package:pritunl/models/server.dart' as svr;
 5 | 
 6 | import 'package:angular/angular.dart' show Injectable;
 7 | import 'package:angular/angular.dart' as ng;
 8 | 
 9 | @Injectable()
10 | class Servers extends collec.Collection {
11 |   Type model = svr.Server;
12 | 
13 |   Servers(ng.Http http) : super(http);
14 | 
15 |   String get url {
16 |     return '/server';
17 |   }
18 | }
19 | 


--------------------------------------------------------------------------------
/www/dart/lib/components/alert/alert.scss:
--------------------------------------------------------------------------------
 1 | @import 'styles/base.scss';
 2 | 
 3 | .alert {
 4 |   padding: 10px;
 5 |   margin-bottom: 10px;
 6 |   border-width: 1px;
 7 |   border-style: solid;
 8 |   @include border-radius-default;
 9 | }
10 | 
11 | .alert btn {
12 |   float: right;
13 |   top: -1px;
14 |   position: relative;
15 |   margin-right: 2px;
16 | }
17 | 
18 | .alert.flash-on {
19 |   @include transition(background-color .175s);
20 | }
21 | 
22 | .alert.flash-off {
23 |   @include transition(background-color .175s);
24 | }
25 | 
26 | .alert.ng-enter {
27 |   @include transition(opacity .15s linear);
28 |   @include opacity(0);
29 | }
30 | 
31 | .alert.ng-enter-active {
32 |   @include transition(opacity .15s linear);
33 |   @include opacity(1);
34 | }
35 | 
36 | .alert.ng-leave {
37 |   @include transition(opacity .15s linear);
38 |   @include opacity(1);
39 | }
40 | 
41 | .alert.ng-leave-active {
42 |   @include transition(opacity .15s linear);
43 |   @include opacity(0);
44 | }
45 | 


--------------------------------------------------------------------------------
/www/dart/lib/components/alert_global/alert_global.dart:
--------------------------------------------------------------------------------
 1 | library alert_global_comp;
 2 | 
 3 | import 'package:pritunl/alert.dart' as alrt;
 4 | 
 5 | import 'package:angular/angular.dart' show Component;
 6 | import 'dart:collection' as collection;
 7 | 
 8 | @Component(
 9 |   selector: 'x-alert-global',
10 |   template: '<x-alert ng-repeat="alert in alerts" type="alert.type" '
11 |     'text="alert.text" on-dismiss="onDismiss(alert)" dismissible></x-alert>'
12 | )
13 | class AlertGlobalComp {
14 |   collection.Queue<alrt.Alert> alerts = alrt.alerts;
15 | 
16 |   void onDismiss(alrt.Alert alert) {
17 |     this.alerts.remove(alert);
18 |   }
19 | }
20 | 


--------------------------------------------------------------------------------
/www/dart/lib/components/boilerplate/boilerplate.dart:
--------------------------------------------------------------------------------
 1 | library boilerplate_comp;
 2 | 
 3 | import 'package:angular/angular.dart' show Component, NgTwoWay, NgAttr;
 4 | 
 5 | @Component(
 6 |   selector: 'x-boilerplate',
 7 |   templateUrl: 'packages/pritunl/components/boilerplate/boilerplate.html',
 8 |   cssUrl: 'packages/pritunl/components/boilerplate/boilerplate.css'
 9 | )
10 | class BoilerplateComp {
11 |   BoilerplateComp() {
12 |   }
13 | }
14 | 


--------------------------------------------------------------------------------
/www/dart/lib/components/boilerplate/boilerplate.html:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/dart/lib/components/boilerplate/boilerplate.html


--------------------------------------------------------------------------------
/www/dart/lib/components/boilerplate/boilerplate.scss:
--------------------------------------------------------------------------------
1 | @import 'styles/base.scss';
2 | 


--------------------------------------------------------------------------------
/www/dart/lib/components/box_label/box_label.dart:
--------------------------------------------------------------------------------
 1 | library box_label_comp;
 2 | 
 3 | import 'package:angular/angular.dart' show Component, NgAttr;
 4 | import 'package:angular/angular.dart' as ng;
 5 | import 'dart:html' as dom;
 6 | 
 7 | @Component(
 8 |   selector: 'x-box-label',
 9 |   template: '<span ng-class="[type, size]"><content></content></span>',
10 |   cssUrl: 'packages/pritunl/components/box_label/box_label.css'
11 | )
12 | class BoxLabelComp implements ng.ShadowRootAware {
13 |   @NgAttr('padding')
14 |   String padding;
15 | 
16 |   @NgAttr('type')
17 |   String type;
18 | 
19 |   @NgAttr('size')
20 |   String size;
21 | 
22 |   onShadowRoot(dom.ShadowRoot root) {
23 |     if (this.padding != null) {
24 |       root.querySelector('span').style.padding = this.padding;
25 |     }
26 |   }
27 | }
28 | 


--------------------------------------------------------------------------------
/www/dart/lib/components/box_label/box_label.scss:
--------------------------------------------------------------------------------
 1 | @import 'styles/base.scss';
 2 | 
 3 | span {
 4 |   display: inline;
 5 |   padding: .2em .6em .3em;
 6 |   font-size: 75%;
 7 |   font-weight: bold;
 8 |   line-height: 1;
 9 |   text-align: center;
10 |   white-space: nowrap;
11 |   vertical-align: baseline;
12 |   @include border-radius-default;
13 | }
14 | 
15 | .large {
16 |   padding: 9px 12px;
17 | }
18 | 


--------------------------------------------------------------------------------
/www/dart/lib/components/checkbox/checkbox.dart:
--------------------------------------------------------------------------------
 1 | library checkbox_comp;
 2 | 
 3 | import 'package:angular/angular.dart' show Component, NgTwoWay, NgCallback;
 4 | import 'dart:html' as dom;
 5 | 
 6 | @Component(
 7 |   selector: 'x-checkbox',
 8 |   template: r'<div ng-click="onClick($event)">'
 9 |     '<x-glyphicon type="ok" ng-if="state"></x-glyphicon></div>',
10 |   cssUrl: 'packages/pritunl/components/checkbox/checkbox.css'
11 | )
12 | class CheckboxComp {
13 |   @NgTwoWay('state')
14 |   bool state;
15 | 
16 |   @NgCallback('on-select')
17 |   Function onSelect;
18 | 
19 |   void onClick(dom.MouseEvent evt) {
20 |     if (this.onSelect != null) {
21 |       this.onSelect({r'$shift': evt.shiftKey});
22 |     }
23 |     else {
24 |       this.state = this.state != true;
25 |     }
26 |   }
27 | }
28 | 


--------------------------------------------------------------------------------
/www/dart/lib/components/checkbox/checkbox.scss:
--------------------------------------------------------------------------------
 1 | @import 'styles/base.scss';
 2 | 
 3 | div {
 4 |   width: 19px;
 5 |   height: 19px;
 6 |   padding-left: 1px;
 7 |   border-width: 1px;
 8 |   border-style: solid;
 9 |   cursor: pointer;
10 |   display: inline-block;
11 |   @include border-radius-default;
12 | }
13 | 
14 | x-glyphicon {
15 |   position: relative;
16 |   top: -1px;
17 |   font-size: 14px;
18 | }
19 | 


--------------------------------------------------------------------------------
/www/dart/lib/components/container/container.dart:
--------------------------------------------------------------------------------
 1 | library container_comp;
 2 | 
 3 | import 'package:angular/angular.dart' show Component;
 4 | 
 5 | @Component(
 6 |   selector: 'x-container',
 7 |   template: '<div class="container"><content></content></div>',
 8 |   cssUrl: 'packages/pritunl/components/container/container.css'
 9 | )
10 | class ContainerComp {
11 | }
12 | 


--------------------------------------------------------------------------------
/www/dart/lib/components/container/container.scss:
--------------------------------------------------------------------------------
 1 | @import 'styles/base.scss';
 2 | 
 3 | .container {
 4 |   width: 940px;
 5 |   padding-right: 15px;
 6 |   padding-left: 15px;
 7 |   margin-right: auto;
 8 |   margin-left: auto;
 9 | }
10 | 
11 | .container:before,
12 | .container:after {
13 |   display: table;
14 |   content: " ";
15 | }
16 | 
17 | .container,
18 | .container:after {
19 |   clear: both;
20 | }
21 | 


--------------------------------------------------------------------------------
/www/dart/lib/components/form_group/form_group.dart:
--------------------------------------------------------------------------------
 1 | library form_group_comp;
 2 | 
 3 | import 'package:angular/angular.dart' show Component;
 4 | 
 5 | @Component(
 6 |   selector: 'x-form-group',
 7 |   template: '<content></content>',
 8 |   cssUrl: 'packages/pritunl/components/form_group/form_group.css'
 9 | )
10 | class FormGroupComp {
11 | }
12 | 


--------------------------------------------------------------------------------
/www/dart/lib/components/form_group/form_group.scss:
--------------------------------------------------------------------------------
 1 | @import 'styles/base.scss';
 2 | 
 3 | ::content label {
 4 |   display: inline-block;
 5 |   margin-bottom: 5px;
 6 | }
 7 | 
 8 | ::content x-form-input,
 9 | ::content x-form-textarea,
10 | ::content x-form-select {
11 |   display: block;
12 |   margin-bottom: 20px;
13 | }
14 | 


--------------------------------------------------------------------------------
/www/dart/lib/components/form_input/form_input.scss:
--------------------------------------------------------------------------------
 1 | @import 'styles/base.scss';
 2 | 
 3 | input {
 4 |   display: inline-block;
 5 |   width: 100%;
 6 |   height: 34px;
 7 |   padding: 6px 12px;
 8 |   font-size: 14px;
 9 |   line-height: 1.42857143;
10 |   background-image: none;
11 |   border-width: 1px;
12 |   border-style: solid;
13 |   @include border-radius-default;
14 |   @include box-shadow((inset 0 1px 1px rgba(0, 0, 0, .075)));
15 |   @include transition((
16 |     border-color ease-in-out 0.15s,
17 |     box-shadow ease-in-out 0.15s
18 |   ))
19 | }
20 | 
21 | input:focus {
22 |   outline: 0;
23 | }
24 | 
25 | input::-moz-placeholder {
26 |   opacity: 1;
27 | }
28 | 
29 | input[disabled],
30 | input[readonly] {
31 |   cursor: default;
32 |   opacity: 1;
33 | }
34 | 


--------------------------------------------------------------------------------
/www/dart/lib/components/form_select/form_select.scss:
--------------------------------------------------------------------------------
 1 | @import 'styles/base.scss';
 2 | 
 3 | select {
 4 |   display: inline-block;
 5 |   width: 100%;
 6 |   height: 34px;
 7 |   padding: 6px 12px;
 8 |   font-size: 14px;
 9 |   line-height: 1.42857143;
10 |   background-image: none;
11 |   border-width: 1px;
12 |   border-style: solid;
13 |   @include border-radius-default;
14 |   @include box-shadow((inset 0 1px 1px rgba(0, 0, 0, .075)));
15 |   @include transition((
16 |     border-color ease-in-out 0.15s,
17 |     box-shadow ease-in-out 0.15s
18 |   ))
19 | }
20 | 
21 | select:focus {
22 |   outline: 0;
23 | }
24 | 
25 | select[disabled],
26 | select[readonly] {
27 |   cursor: not-allowed;
28 |   opacity: 1;
29 | }
30 | 


--------------------------------------------------------------------------------
/www/dart/lib/components/form_textarea/form_textarea.dart:
--------------------------------------------------------------------------------
 1 | library form_textarea_comp;
 2 | 
 3 | import 'package:pritunl/bases/form_control/form_control.dart' as
 4 |   form_control_base;
 5 | 
 6 | import 'package:angular/angular.dart' show Component, NgTwoWay, NgAttr;
 7 | 
 8 | @Component(
 9 |   selector: 'x-form-textarea',
10 |   template: '<textarea placeholder="{{placeholder}}" '
11 |     'ng-model="model" tooltip="{{formTooltip}}" rows="{{rows}}" '
12 |     'spellcheck="{{spellcheck}}"></textarea>',
13 |   cssUrl: 'packages/pritunl/components/form_textarea/form_textarea.css'
14 | )
15 | class FormTextareaComp extends form_control_base.FormControlBase {
16 |   String controlSelector = 'input';
17 | 
18 |   @NgAttr('form-tooltip')
19 |   String formTooltip;
20 | 
21 |   @NgAttr('rows')
22 |   String rows;
23 | 
24 |   @NgAttr('spellcheck')
25 |   String spellcheck;
26 | 
27 |   @NgAttr('placeholder')
28 |   String placeholder;
29 | 
30 |   @NgTwoWay('model')
31 |   String model;
32 | }
33 | 


--------------------------------------------------------------------------------
/www/dart/lib/components/form_textarea/form_textarea.scss:
--------------------------------------------------------------------------------
 1 | @import 'styles/base.scss';
 2 | 
 3 | textarea {
 4 |   display: inline-block;
 5 |   width: 100%;
 6 |   padding: 6px 12px;
 7 |   font-size: 14px;
 8 |   line-height: 1.42857143;
 9 |   background-image: none;
10 |   border-width: 1px;
11 |   border-style: solid;
12 |   resize: none;
13 |   font-family: 'Lucida Console', Monaco, monospace;
14 |   @include border-radius-default;
15 |   @include box-shadow((inset 0 1px 1px rgba(0, 0, 0, .075)));
16 |   @include transition((
17 |     border-color ease-in-out 0.15s,
18 |     box-shadow ease-in-out 0.15s
19 |   ))
20 | }
21 | 
22 | textarea:focus {
23 |   outline: 0;
24 | }
25 | 
26 | textarea::-moz-placeholder {
27 |   opacity: 1;
28 | }
29 | 
30 | textarea[disabled],
31 | textarea[readonly] {
32 |   cursor: not-allowed;
33 |   opacity: 1;
34 | }
35 | 


--------------------------------------------------------------------------------
/www/dart/lib/components/fraction/fraction.scss:
--------------------------------------------------------------------------------
1 | @import 'styles/base.scss';
2 | 


--------------------------------------------------------------------------------
/www/dart/lib/components/glyphicon/glyphicon.dart:
--------------------------------------------------------------------------------
 1 | library glyphicon_comp;
 2 | 
 3 | import 'package:angular/angular.dart' show Component, NgAttr;
 4 | 
 5 | @Component(
 6 |   selector: 'x-glyphicon',
 7 |   template: '<span ng-class="iconClass"></span>',
 8 |   cssUrl: 'packages/pritunl/components/glyphicon/glyphicon.css'
 9 | )
10 | class GlyphiconComp {
11 |   @NgAttr('type')
12 |   String type;
13 | 
14 |   String get iconClass {
15 |     return 'glyphicon glyphicon-${this.type}';
16 |   }
17 | }
18 | 


--------------------------------------------------------------------------------
/www/dart/lib/components/log_entries/log_entries.dart:
--------------------------------------------------------------------------------
 1 | library log_entries_comp;
 2 | 
 3 | import 'package:pritunl/collections/log_entries.dart' as log_ents;
 4 | 
 5 | import 'package:angular/angular.dart' show Component;
 6 | 
 7 | @Component(
 8 |   selector: 'x-log-entries',
 9 |   templateUrl: 'packages/pritunl/components/log_entries/log_entries.html',
10 |   cssUrl: 'packages/pritunl/components/log_entries/log_entries.css'
11 | )
12 | class LogEntriesComp {
13 |   log_ents.LogEntries entries;
14 | 
15 |   LogEntriesComp(this.entries) {
16 |     this.update();
17 |   }
18 | 
19 |   void update() {
20 |     this.entries.fetch();
21 |   }
22 | }
23 | 


--------------------------------------------------------------------------------
/www/dart/lib/components/log_entries/log_entries.html:
--------------------------------------------------------------------------------
 1 | <div class="log-container">
 2 |   <h2 class="title">Recent log entries</h2>
 3 |   <ul class="entries">
 4 |     <li class="entry clearfix" ng-repeat="entry in entries">
 5 |       <x-glyphicon type="record"></x-glyphicon>
 6 |       <span class="message" ng-bind="entry.message"></span>
 7 |       <span class="time" ng-bind="entry.timestamp | datetime"></span>
 8 |     </li>
 9 |   </ul>
10 | </div>
11 | 


--------------------------------------------------------------------------------
/www/dart/lib/components/modal/modal.html:
--------------------------------------------------------------------------------
 1 | <div class="container" ng-if="state" ng-animate>
 2 |   <div class="backdrop"></div>
 3 |   <div class="modal" ng-click="softClose($event.target)">
 4 |     <form class="content">
 5 |       <div class="header">
 6 |         <btn type="close" ng-click="hardClose()"></btn>
 7 |         <h4 class="title">{{title}}</h4>
 8 |         <div ng-if="advanced" class="advanced" no-select>Advanced</div>
 9 |       </div>
10 |       <div class="body">
11 |         <content></content>
12 |       </div>
13 |       <div class="footer">
14 |         <x-btn ng-if="noCancel != true" type="default" ng-click="hardClose()"
15 |           disabled="cancelDisabled">{{cancelText}}</x-btn>
16 |         <x-btn ng-if="noOk != true" type="primary" ng-click="submit()"
17 |           disabled="okDisabled" form-submit>{{okText}}</x-btn>
18 |       </div>
19 |     </form>
20 |   </div>
21 | </div>
22 | 


--------------------------------------------------------------------------------
/www/dart/lib/components/navbar/navbar.dart:
--------------------------------------------------------------------------------
 1 | library navbar_comp;
 2 | 
 3 | import 'package:pritunl/settings/settings.dart' as settings;
 4 | 
 5 | import 'package:angular/angular.dart' show Component;
 6 | 
 7 | @Component(
 8 |     selector: 'x-navbar',
 9 |     templateUrl: 'packages/pritunl/components/navbar/navbar.html',
10 |     cssUrl: 'packages/pritunl/components/navbar/navbar.css'
11 | )
12 | class NavbarComp {
13 |   Map<String, String> active;
14 | 
15 |   NavbarComp() {
16 |     settings.set('active_page', this);
17 |     settings.observe('active_page', (_, value) {
18 |       this.active = {value: 'active'};
19 |     });
20 |   }
21 | }
22 | 


--------------------------------------------------------------------------------
/www/dart/lib/components/navbar/navbar.html:
--------------------------------------------------------------------------------
 1 | <nav no-select>
 2 |   <x-container>
 3 |     <header>
 4 |       <a class="brand standard-brand" href="/s">pritunl</a>
 5 |       <a class="brand premium-brand" href="/s">pritunl premium</a>
 6 |       <a class="brand enterprise-brand" href="/s">pritunl enterprise</a>
 7 |     </header>
 8 |     <ul class="links" ng-class="active">
 9 |       <li ng-class="active['dashboard']"><a
10 |         href="/s/#/dashboard">Dashboard</a></li>
11 |       <li ng-class="active['users']"><a href="/s/#/users">Users</a></li>
12 |       <li ng-class="active['servers']"><a href="/s/#/servers">Servers</a></li>
13 |       <li><a href="/s/#/hosts">Hosts</a></li>
14 |     </ul>
15 |     <ul class="links links-right">
16 |       <li><a><box-label type="default">Upgrade to Premium!</box-label></a></li>
17 |       <li><a>Subscription</a></li>
18 |       <li><a>Settings</a></li>
19 |       <li><a href="/s/#/logout">Logout</a></li>
20 |     </ul>
21 |     <x-box-label class="feedback" type="success">Provide Feedback</x-box-label>
22 |   </x-container>
23 | </nav>
24 | 


--------------------------------------------------------------------------------
/www/dart/lib/components/org_add/org_add.html:
--------------------------------------------------------------------------------
 1 | <x-modal title="Add Organization" ok-text="Add"
 2 |     ok-disabled="okDisabled">
 3 |   <x-alert type="alertType" text="alertText"></x-alert>
 4 |   <x-form-group>
 5 |     <label>Name</label>
 6 |     <x-form-input class="name" type="text" model="model.name"
 7 |       placeholder="Name of organization"
 8 |       form-tooltip="Enter name"></x-form-input>
 9 |   </x-form-group>
10 | </x-modal>
11 | 


--------------------------------------------------------------------------------
/www/dart/lib/components/org_del/org_del.html:
--------------------------------------------------------------------------------
 1 | <x-modal title="Delete Organization" ok-text="Delete" ok-disabled="okDisabled">
 2 |   <x-alert type="'danger'">Deleting the organization will delete all the users
 3 |     in it. Any servers that are attached to the organization will be
 4 |     stopped.</x-alert>
 5 |   <x-alert type="alertType" text="alertText"></x-alert>
 6 |   <x-form-group>
 7 |     <label>Enter the name of the organization to confirm</label>
 8 |     <x-form-input class="name" type="text" model="nameConfirm"
 9 |       placeholder="Name of organization"
10 |       form-tooltip="Enter name"></x-form-input>
11 |   </x-form-group>
12 | </x-modal>
13 | 


--------------------------------------------------------------------------------
/www/dart/lib/components/org_modify/org_modify.html:
--------------------------------------------------------------------------------
 1 | <x-modal title="Modify Organization" ok-text="Rename"
 2 |     ok-disabled="okDisabled">
 3 |   <x-alert type="alertType" text="alertText"></x-alert>
 4 |   <x-form-group>
 5 |     <label>Rename {{origModel.name}}</label>
 6 |     <x-form-input class="name" type="text" model="model.name"
 7 |       placeholder="Name of organization"
 8 |       form-tooltip="Enter new name"></x-form-input>
 9 |   </x-form-group>
10 | </x-modal>
11 | 


--------------------------------------------------------------------------------
/www/dart/lib/components/organizations/organizations.html:
--------------------------------------------------------------------------------
 1 | <div class="header">
 2 |   <h1 class="title">Users and Organizations</h1>
 3 |   <div class="buttons">
 4 |     <x-org-add></x-org-add>
 5 |     <x-btn type="primary" modal-attach="x-org-add">Add Organization</x-btn>
 6 |     <x-user-add orgs="orgs"></x-user-add>
 7 |     <x-btn type="primary" modal-attach="x-user-add">Add User</x-btn>
 8 |     <x-user-add-bulk orgs="orgs"></x-user-add-bulk>
 9 |     <x-btn type="primary" modal-attach="x-user-add-bulk">Bulk Add Users</x-btn>
10 |     <x-user-email users="selected"></x-user-email>
11 |     <x-btn type="warning" modal-attach="x-user-email"
12 |       disabled="selected.length == 0">Email Selected</x-btn>
13 |     <x-user-del users="selected"></x-user-del>
14 |     <x-btn type="danger" modal-attach="x-user-del"
15 |       disabled="selected.length == 0">Delete Selected</x-btn>
16 |   </div>
17 | </div>
18 | <x-alert-global></x-alert-global>
19 | <ul>
20 |   <li class="org" ng-repeat="org in orgs">
21 |     <x-organization model="org" selected="selected"></x-organization>
22 |   </li>
23 |   <li ng-if="message != null" class="message">
24 |     <span ng-bind="message"></span>
25 |   </li>
26 | </ul>
27 | 


--------------------------------------------------------------------------------
/www/dart/lib/components/organizations/organizations.scss:
--------------------------------------------------------------------------------
 1 | @import 'styles/base.scss';
 2 | 
 3 | .header .title {
 4 |   margin-top: 6px;
 5 |   margin-bottom: 19px;
 6 |   font-size: 22px;
 7 |   display: inline-block;
 8 | }
 9 | 
10 | .header .buttons {
11 |   float: right;
12 |   display: block;
13 | }
14 | 
15 | .header .buttons button {
16 |   margin-top: 2px;
17 | }
18 | 
19 | .message {
20 |   margin-bottom: 25px;
21 |   border-width: 1px;
22 |   border-style: solid;
23 |   text-align: center;
24 |   font-size: 14px;
25 |   padding: 10px;
26 |   @include border-radius-default;
27 |   @include box-shadow((
28 |     0 2px 1px rgba(0, 0, 0, 0.05),
29 |     0 -1px 2px rgba(0, 0, 0, 0.05) inset
30 |   ))
31 | }
32 | 


--------------------------------------------------------------------------------
/www/dart/lib/components/qrcode/qrcode.html:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/dart/lib/components/qrcode/qrcode.html


--------------------------------------------------------------------------------
/www/dart/lib/components/server_del/server_del.html:
--------------------------------------------------------------------------------
 1 | <x-modal title="Delete Server" ok-text="Delete" ok-disabled="okDisabled">
 2 |   <x-alert type="alertType" text="alertText"></x-alert>
 3 |   <x-form-group>
 4 |     <label>Enter the name of the server to confirm</label>
 5 |     <x-form-input class="name" type="text" model="nameConfirm"
 6 |       placeholder="Name of server"
 7 |       form-tooltip="Enter name"></x-form-input>
 8 |   </x-form-group>
 9 | </x-modal>
10 | 


--------------------------------------------------------------------------------
/www/dart/lib/components/servers/servers.html:
--------------------------------------------------------------------------------
 1 | <div class="header">
 2 |   <h1 class="title">Servers</h1>
 3 |   <div class="buttons">
 4 |     <x-btn type="primary">Add Server</x-btn>
 5 |     <x-btn type="primary">Attach Organization</x-btn>
 6 |     <x-btn type="primary">Attach Host</x-btn>
 7 |     <x-btn type="primary">Link Server</x-btn>
 8 |   </div>
 9 | </div>
10 | <x-alert-global></x-alert-global>
11 | <ul>
12 |   <li class="server" ng-repeat="server in servers">
13 |     <x-server model="server"></x-server>
14 |   </li>
15 |   <li ng-if="message != null" class="message">
16 |     <span ng-bind="message"></span>
17 |   </li>
18 | </ul>
19 | 


--------------------------------------------------------------------------------
/www/dart/lib/components/servers/servers.scss:
--------------------------------------------------------------------------------
 1 | @import 'styles/base.scss';
 2 | 
 3 | .header .title {
 4 |   margin-top: 6px;
 5 |   margin-bottom: 19px;
 6 |   font-size: 22px;
 7 |   display: inline-block;
 8 | }
 9 | 
10 | .header .buttons {
11 |   float: right;
12 |   display: block;
13 | }
14 | 
15 | .header .buttons button {
16 |   margin-top: 2px;
17 | }
18 | 
19 | .message {
20 |   margin-bottom: 25px;
21 |   border-width: 1px;
22 |   border-style: solid;
23 |   text-align: center;
24 |   font-size: 14px;
25 |   padding: 10px;
26 |   @include border-radius-default;
27 |   @include box-shadow((
28 |     0 2px 1px rgba(0, 0, 0, 0.05),
29 |     0 -1px 2px rgba(0, 0, 0, 0.05) inset
30 |   ))
31 | }
32 | 


--------------------------------------------------------------------------------
/www/dart/lib/components/status/status.dart:
--------------------------------------------------------------------------------
 1 | library status_comp;
 2 | 
 3 | import 'package:pritunl/models/status.dart' as stus;
 4 | 
 5 | import 'package:angular/angular.dart' show Component;
 6 | 
 7 | @Component(
 8 |     selector: 'x-status',
 9 |     templateUrl: 'packages/pritunl/components/status/status.html',
10 |     cssUrl: 'packages/pritunl/components/status/status.css'
11 | )
12 | class StatusComp {
13 |   stus.Status model;
14 | 
15 |   StatusComp(this.model) {
16 |     this.update();
17 |   }
18 | 
19 |   void update() {
20 |     this.model.fetch();
21 |   }
22 | }
23 | 


--------------------------------------------------------------------------------
/www/dart/lib/components/user_add/user_add.html:
--------------------------------------------------------------------------------
 1 | <x-modal title="Add User" ok-text="Add" ok-disabled="okDisabled">
 2 |   <x-alert type="alertType" text="alertText"></x-alert>
 3 |   <x-form-group>
 4 |     <label>Name</label>
 5 |     <x-form-input class="name" type="text" placeholder="Enter name"
 6 |       model="model.name" form-tooltip="Enter name"></x-form-input>
 7 |   </x-form-group>
 8 |   <x-form-group>
 9 |     <label>Select an organization</label>
10 |     <x-form-select class="org" model="model.organization" collection="orgs"
11 |       form-tooltip="Organization to add user to"
12 |       opt-value="$model.id" opt-text="$model.name"></x-form-select>
13 |   </x-form-group>
14 |   <x-form-group>
15 |     <label>Email (optional)</label>
16 |     <x-form-input class="email" type="text" placeholder="Enter email address"
17 |       model="model.email" form-tooltip="Email address of user"></x-form-input>
18 |   </x-form-group>
19 | </x-modal>
20 | 


--------------------------------------------------------------------------------
/www/dart/lib/components/user_add_bulk/user_add_bulk.html:
--------------------------------------------------------------------------------
 1 | <x-modal title="Bulk Add Users" ok-text="Add" ok-disabled="okDisabled">
 2 |   <x-alert type="alertType" text="alertText"></x-alert>
 3 |   <x-form-group>
 4 |     <label>Enter list of usernames and optionally an email addresses on
 5 |       each line with a comma separating the username from the email
 6 |       address</label>
 7 |     <x-form-textarea class="users" type="text" model="users"
 8 |       rows="12" spellcheck="false"
 9 |       placeholder="user1,user1@pritunl.com"></x-form-textarea>
10 |   </x-form-group>
11 |   <x-form-group>
12 |     <label>Select an organization</label>
13 |     <x-form-select class="org" model="model.org" collection="orgs"
14 |       form-tooltip="Organization to add user to"
15 |       opt-value="$model.id" opt-text="$model.name"></x-form-select>
16 |   </x-form-group>
17 | </x-modal>
18 | 


--------------------------------------------------------------------------------
/www/dart/lib/components/user_del/user_del.html:
--------------------------------------------------------------------------------
1 | <x-modal title="Delete Users" ok-text="Delete" ok-disabled="okDisabled">
2 |   <x-alert type="alertType" text="alertText"></x-alert>
3 |   <label>Are you sure you want to delete the following users?</label>
4 |   <ul class="users">
5 |     <li ng-repeat="user in users" ng-bind="user.name"></li>
6 |   </ul>
7 | </x-modal>
8 | 


--------------------------------------------------------------------------------
/www/dart/lib/components/user_del/user_del.scss:
--------------------------------------------------------------------------------
 1 | @import 'styles/base.scss';
 2 | 
 3 | modal .users {
 4 |   padding-left: 30px;
 5 |   margin-top: 5px;
 6 |   margin-bottom: 20px;
 7 | }
 8 | 
 9 | modal .users li {
10 |   list-style-type: disc;
11 | }
12 | 


--------------------------------------------------------------------------------
/www/dart/lib/components/user_email/user_email.html:
--------------------------------------------------------------------------------
 1 | <x-modal title="Email Users" ok-text="{{okText}}" no-cancel="{{noCancel}}"
 2 |     ok-disabled="okDisabled">
 3 |   <x-alert type="alertType" text="alertText"></x-alert>
 4 |   <label>Are you sure you want to email a key link to the following
 5 |     users?</label>
 6 |   <ul class="users">
 7 |     <li ng-repeat="user in users" ng-bind="getUserData(user)"
 8 |       ng-class="userClass[user]"></li>
 9 |   </ul>
10 | </x-modal>
11 | 


--------------------------------------------------------------------------------
/www/dart/lib/components/user_email/user_email.scss:
--------------------------------------------------------------------------------
 1 | @import 'styles/base.scss';
 2 | 
 3 | modal .users {
 4 |   padding-left: 30px;
 5 |   margin-top: 5px;
 6 |   margin-bottom: 20px;
 7 | }
 8 | 
 9 | modal .users li {
10 |   list-style-type: disc;
11 | }
12 | 


--------------------------------------------------------------------------------
/www/dart/lib/components/user_key_links/user_key_links.dart:
--------------------------------------------------------------------------------
 1 | library user_key_links_comp;
 2 | 
 3 | import 'package:pritunl/bases/modal_content/modal_content.dart' as
 4 |   modal_content_base;
 5 | import 'package:pritunl/models/user.dart' as usr;
 6 | import 'package:pritunl/models/key.dart' as ky;
 7 | 
 8 | import 'package:angular/angular.dart' show Component, NgOneWayOneTime;
 9 | 
10 | @Component(
11 |   selector: 'x-user-key-links',
12 |   templateUrl: 'packages/pritunl/components/user_key_links/user_key_links.html',
13 |   cssUrl: 'packages/pritunl/components/user_key_links/user_key_links.css'
14 | )
15 | class UserKeyLinksComp extends modal_content_base.ModalContent {
16 |   ky.Key model;
17 | 
18 |   @NgOneWayOneTime('model')
19 |   usr.User user;
20 | 
21 |   UserKeyLinksComp(this.model);
22 | 
23 |   void show() {
24 |     this.model.user = this.user.id;
25 |     this.model.org = this.user.organization;
26 |     this.model.fetch();
27 |   }
28 | }
29 | 


--------------------------------------------------------------------------------
/www/dart/lib/components/user_key_links/user_key_links.scss:
--------------------------------------------------------------------------------
1 | a {
2 |   float: right;
3 |   top: -49px;
4 |   left: -7px;
5 |   position: relative;
6 |   font-size: 21px;
7 | }
8 | 


--------------------------------------------------------------------------------
/www/dart/lib/components/user_modify/user_modify.html:
--------------------------------------------------------------------------------
 1 | <x-modal title="Modify User" ok-text="Save" ok-disabled="okDisabled">
 2 |   <x-alert type="alertType" text="alertText"></x-alert>
 3 |   <fx-orm-group>
 4 |     <label>Name</label>
 5 |     <x-form-input class="name" type="text" placeholder="Enter name"
 6 |       model="model.name" form-tooltip="Enter name"></x-form-input>
 7 |   </fx-orm-group>
 8 |   <fx-orm-group>
 9 |     <label>Email (optional)</label>
10 |     <x-form-input class="email" type="text" placeholder="Enter email address"
11 |       model="model.email" form-tooltip="Email address of user"></x-form-input>
12 |   </fx-orm-group>
13 | </x-modal>
14 | 


--------------------------------------------------------------------------------
/www/dart/lib/components/user_otp/user_otp.html:
--------------------------------------------------------------------------------
 1 | <x-modal title="Two-Step Authentication Key" no-cancel>
 2 |   <x-alert type="alertType" text="alertText"></x-alert>
 3 |   <label>Two-step authentication key</label>
 4 |   <x-form-input class="name" width="190px" value="model.otpSecret"
 5 |     type="text" readonly click-select></x-form-input>
 6 |   <x-qrcode width="192" height="192" text="qrcodeText"></x-qrcode>
 7 |   <x-btn type="danger" width="190px" ng-click="newKey()"
 8 |     disabled="genKeyDisabled">Generate New Key</x-btn>
 9 | </x-modal>
10 | 


--------------------------------------------------------------------------------
/www/dart/lib/components/user_otp/user_otp.scss:
--------------------------------------------------------------------------------
 1 | label,
 2 | x-form-input,
 3 | x-btn {
 4 |   display: block;
 5 |   text-align: center;
 6 | }
 7 | 
 8 | label {
 9 |   margin-bottom: 5px;
10 | }
11 | 
12 | x-form-input {
13 |   margin-bottom: 15px;
14 | }
15 | 
16 | x-btn {
17 |   margin-top: 15px;
18 |   margin-bottom: 20px;
19 | }
20 | 


--------------------------------------------------------------------------------
/www/dart/lib/decorators/autofocus.dart:
--------------------------------------------------------------------------------
 1 | library autofocus_dec;
 2 | 
 3 | import 'package:angular/angular.dart' show Decorator;
 4 | import 'package:angular/angular.dart' as ng;
 5 | import 'dart:html' as dom;
 6 | 
 7 | @Decorator(
 8 |   selector: '[autofocus]'
 9 | )
10 | class AutoFocusDec implements ng.AttachAware {
11 |   dom.Element element;
12 | 
13 |   AutoFocusDec(this.element);
14 | 
15 |   void attach() {
16 |     element.focus();
17 |   }
18 | }
19 | 


--------------------------------------------------------------------------------
/www/dart/lib/decorators/conditional.dart:
--------------------------------------------------------------------------------
 1 | library conditional_dec;
 2 | 
 3 | import 'package:angular/angular.dart' as ng;
 4 | import 'dart:html' as dom;
 5 | 
 6 | abstract class Conditional {
 7 |   final ng.ViewFactory _viewFactory;
 8 |   final ng.ViewPort _viewPort;
 9 |   final ng.Scope _scope;
10 |   ng.View _view;
11 |   dom.Element element;
12 | 
13 |   Conditional(this._viewFactory, this._viewPort, this._scope);
14 | 
15 |   void set condition(value) {
16 |     if (value == true) {
17 |       this._ensureViewExists();
18 |     } else {
19 |       this._ensureViewDestroyed();
20 |     }
21 |   }
22 | 
23 |   void _ensureViewExists() {
24 |     if (this._view == null) {
25 |       this._view = this._viewPort.insertNew(this._viewFactory);
26 |       this.element = this._view.nodes[0];
27 |     }
28 |   }
29 | 
30 |   void _ensureViewDestroyed() {
31 |     if (this._view != null) {
32 |       this._viewPort.remove(this._view);
33 |       this._view = null;
34 |       this.element = null;
35 |     }
36 |   }
37 | }
38 | 


--------------------------------------------------------------------------------
/www/dart/lib/decorators/decorators.dart:
--------------------------------------------------------------------------------
 1 | library decorators;
 2 | 
 3 | import 'package:pritunl/decorators/autofocus.dart' as autofocus;
 4 | import 'package:pritunl/decorators/modal.dart' as modal;
 5 | import 'package:pritunl/decorators/modal_attach.dart' as modal_attach;
 6 | import 'package:pritunl/decorators/noselect.dart' as noselect;
 7 | import 'package:pritunl/decorators/shift_click.dart' as shift_click;
 8 | import 'package:pritunl/decorators/tooltip.dart' as tooltip;
 9 | 
10 | import 'package:angular/angular.dart' as ng;
11 | 
12 | class DecoratorsMod extends ng.Module {
13 |   DecoratorsMod() {
14 |     this.bind(autofocus.AutoFocusDec);
15 |     this.bind(modal.ModalDec);
16 |     this.bind(modal_attach.ModalAttachDec);
17 |     this.bind(noselect.NoSelectDec);
18 |     this.bind(shift_click.ShiftClickDec);
19 |     this.bind(tooltip.TooltipDec);
20 |   }
21 | }
22 | 


--------------------------------------------------------------------------------
/www/dart/lib/decorators/noselect.dart:
--------------------------------------------------------------------------------
 1 | library noselect_dec;
 2 | 
 3 | import 'package:angular/angular.dart' show Decorator;
 4 | import 'dart:html' as dom;
 5 | 
 6 | @Decorator(
 7 |   selector: '[no-select]'
 8 | )
 9 | class NoSelectDec {
10 |   NoSelectDec(dom.Element element) {
11 |     element.onMouseDown.listen((evt) {
12 |       evt.preventDefault();
13 |     });
14 |   }
15 | }
16 | 


--------------------------------------------------------------------------------
/www/dart/lib/decorators/shift_click.dart:
--------------------------------------------------------------------------------
 1 | library shift_click_dec;
 2 | 
 3 | import 'package:angular/angular.dart' show Decorator, NgCallback;
 4 | import 'dart:html' as dom;
 5 | 
 6 | @Decorator(
 7 |   selector: '[shift-click]'
 8 | )
 9 | class ShiftClickDec {
10 |   @NgCallback('shift-click')
11 |   Function callback;
12 | 
13 |   ShiftClickDec(dom.Element element) {
14 |     element.onClick.listen((evt) {
15 |       if (evt.shiftKey) {
16 |         this.callback();
17 |       }
18 |     });
19 |   }
20 | }
21 | 


--------------------------------------------------------------------------------
/www/dart/lib/fonts/FontAwesome.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/dart/lib/fonts/FontAwesome.otf


--------------------------------------------------------------------------------
/www/dart/lib/fonts/fontawesome-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/dart/lib/fonts/fontawesome-webfont.eot


--------------------------------------------------------------------------------
/www/dart/lib/fonts/fontawesome-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/dart/lib/fonts/fontawesome-webfont.ttf


--------------------------------------------------------------------------------
/www/dart/lib/fonts/fontawesome-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/dart/lib/fonts/fontawesome-webfont.woff


--------------------------------------------------------------------------------
/www/dart/lib/fonts/fredoka-one.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/dart/lib/fonts/fredoka-one.eot


--------------------------------------------------------------------------------
/www/dart/lib/fonts/fredoka-one.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/dart/lib/fonts/fredoka-one.woff


--------------------------------------------------------------------------------
/www/dart/lib/fonts/glyphicons-halflings-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/dart/lib/fonts/glyphicons-halflings-regular.eot


--------------------------------------------------------------------------------
/www/dart/lib/fonts/glyphicons-halflings-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/dart/lib/fonts/glyphicons-halflings-regular.ttf


--------------------------------------------------------------------------------
/www/dart/lib/fonts/glyphicons-halflings-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/dart/lib/fonts/glyphicons-halflings-regular.woff


--------------------------------------------------------------------------------
/www/dart/lib/fonts/ubuntu-bold.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/dart/lib/fonts/ubuntu-bold.eot


--------------------------------------------------------------------------------
/www/dart/lib/fonts/ubuntu-bold.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/dart/lib/fonts/ubuntu-bold.woff


--------------------------------------------------------------------------------
/www/dart/lib/fonts/ubuntu.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/dart/lib/fonts/ubuntu.eot


--------------------------------------------------------------------------------
/www/dart/lib/fonts/ubuntu.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/dart/lib/fonts/ubuntu.woff


--------------------------------------------------------------------------------
/www/dart/lib/formatters/capitalize.dart:
--------------------------------------------------------------------------------
 1 | library capitalize_form;
 2 | 
 3 | import 'package:angular/angular.dart' show Formatter;
 4 | 
 5 | @Formatter(name: 'capitalize')
 6 | class CapitalizeForm {
 7 |   String call(String input) {
 8 |     if (input == null) {
 9 |       return null;
10 |     }
11 | 
12 |     if (input.length < 1) {
13 |       return input;
14 |     }
15 | 
16 |     return input.substring(0, 1).toUpperCase() + input.substring(1);
17 |   }
18 | }
19 | 


--------------------------------------------------------------------------------
/www/dart/lib/formatters/datetime.dart:
--------------------------------------------------------------------------------
 1 | library datetime_form;
 2 | 
 3 | import 'package:angular/angular.dart' show Formatter;
 4 | 
 5 | @Formatter(name: 'datetime')
 6 | class DatetimeForm {
 7 |   String call(int time) {
 8 |     if (time == null) {
 9 |       return null;
10 |     }
11 | 
12 |     var date = new DateTime.fromMillisecondsSinceEpoch(time * 1000);
13 | 
14 |     var abbrev = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
15 |       'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
16 |     var month = abbrev[date.month - 1];
17 | 
18 |     var day = date.day.toString();
19 | 
20 |     var year = date.year;
21 | 
22 |     var meridiem;
23 |     var hour = date.hour;
24 |     if (hour > 12) {
25 |       meridiem = 'pm';
26 |       hour = (hour - 12).toString();
27 |     }
28 |     else {
29 |       meridiem = 'am';
30 |       hour = hour.toString();
31 |     }
32 | 
33 |     var minute = date.minute.toString();
34 |     if (minute.length < 2) {
35 |       minute = '0$minute';
36 |     }
37 | 
38 |     return '$hour:$minute $meridiem - $month $day $year';
39 |   }
40 | }
41 | 


--------------------------------------------------------------------------------
/www/dart/lib/formatters/formatters.dart:
--------------------------------------------------------------------------------
 1 | library formatters;
 2 | 
 3 | import 'package:pritunl/formatters/capitalize.dart' as capitalize;
 4 | import 'package:pritunl/formatters/datetime.dart' as datetime;
 5 | import 'package:pritunl/formatters/fraction.dart' as fraction;
 6 | import 'package:pritunl/formatters/slash.dart' as slash;
 7 | import 'package:pritunl/formatters/timer.dart' as timer;
 8 | 
 9 | import 'package:angular/angular.dart' as ng;
10 | 
11 | class FormattersMod extends ng.Module {
12 |   FormattersMod() {
13 |     this.bind(capitalize.CapitalizeForm);
14 |     this.bind(datetime.DatetimeForm);
15 |     this.bind(fraction.FractionForm);
16 |     this.bind(slash.SlashForm);
17 |     this.bind(timer.TimerForm);
18 |   }
19 | }
20 | 


--------------------------------------------------------------------------------
/www/dart/lib/formatters/fraction.dart:
--------------------------------------------------------------------------------
 1 | library fraction_form;
 2 | 
 3 | import 'package:angular/angular.dart' show Formatter;
 4 | 
 5 | @Formatter(name: 'fraction')
 6 | class FractionForm {
 7 |   String call(List<int> input) {
 8 |     if (input[0] == null || input[1] == null || (
 9 |         input[0] == 0 && input[1] == 0)) {
10 |       return '-/-';
11 |     }
12 |     return '${input[0]}/${input[1]}';
13 |   }
14 | }
15 | 


--------------------------------------------------------------------------------
/www/dart/lib/formatters/slash.dart:
--------------------------------------------------------------------------------
 1 | library slash_form;
 2 | 
 3 | import 'package:angular/angular.dart' show Formatter;
 4 | 
 5 | @Formatter(name: 'slash')
 6 | class SlashForm {
 7 |   dynamic call(dynamic input) {
 8 |     if (input == null) {
 9 |       return '-';
10 |     }
11 |     return input;
12 |   }
13 | }
14 | 


--------------------------------------------------------------------------------
/www/dart/lib/formatters/timer.dart:
--------------------------------------------------------------------------------
 1 | library timer_form;
 2 | 
 3 | import 'package:angular/angular.dart' show Formatter;
 4 | 
 5 | @Formatter(name: 'timer')
 6 | class TimerForm {
 7 |   String call(int count) {
 8 |     if (count == null || count == 0) {
 9 |       return '-';
10 |     }
11 | 
12 |     var days = (count / 86400).floor();
13 |     count -= days * 86400;
14 | 
15 |     var hours = (count / 3600).floor();
16 |     count -= hours * 3600;
17 | 
18 |     var mins = (count / 60).floor();
19 |     count -= mins * 60;
20 | 
21 |     if (days > 0) {
22 |       return '${days}d ${hours}h ${mins}m ${count}s';
23 |     }
24 |     else if (hours > 0) {
25 |       return '${hours}h ${mins}m ${count}s';
26 |     }
27 |     else if (mins > 0) {
28 |       return '${mins}m ${count}s';
29 |     }
30 |     else {
31 |       return '${count}s';
32 |     }
33 |   }
34 | }
35 | 


--------------------------------------------------------------------------------
/www/dart/lib/models/event.dart:
--------------------------------------------------------------------------------
 1 | library event_mod;
 2 | 
 3 | import 'package:pritunl/model.dart' as mdl;
 4 | 
 5 | import 'package:angular/angular.dart' show Injectable;
 6 | import 'package:angular/angular.dart' as ng;
 7 | 
 8 | @Injectable()
 9 | class Event extends mdl.Model {
10 |   @mdl.Attribute('id')
11 |   String id;
12 | 
13 |   @mdl.Attribute('type')
14 |   String type;
15 | 
16 |   @mdl.Attribute('resource_id')
17 |   String resourceId;
18 | 
19 |   @mdl.Attribute('timestamp')
20 |   double timestamp;
21 | 
22 |   Event(ng.Http http) : super(http);
23 | }
24 | 


--------------------------------------------------------------------------------
/www/dart/lib/models/log_entry.dart:
--------------------------------------------------------------------------------
 1 | library log_entry_mod;
 2 | 
 3 | import 'package:pritunl/model.dart' as mdl;
 4 | 
 5 | import 'package:angular/angular.dart' show Injectable;
 6 | import 'package:angular/angular.dart' as ng;
 7 | 
 8 | @Injectable()
 9 | class LogEntry extends mdl.Model {
10 |   @mdl.Attribute('id')
11 |   String id;
12 | 
13 |   @mdl.Attribute('timestamp')
14 |   int timestamp;
15 | 
16 |   @mdl.Attribute('message')
17 |   String message;
18 | 
19 |   LogEntry(ng.Http http) : super(http);
20 | }
21 | 


--------------------------------------------------------------------------------
/www/dart/lib/models/organization.dart:
--------------------------------------------------------------------------------
 1 | library organization_mod;
 2 | 
 3 | import 'package:pritunl/model.dart' as mdl;
 4 | import 'package:pritunl/collections/users.dart' as usrs;
 5 | 
 6 | import 'package:angular/angular.dart' show Injectable;
 7 | import 'package:angular/angular.dart' as ng;
 8 | 
 9 | @Injectable()
10 | class Organization extends mdl.Model {
11 |   usrs.Users users;
12 | 
13 |   @mdl.Attribute('id')
14 |   String id;
15 | 
16 |   @mdl.Attribute('name')
17 |   String name;
18 | 
19 |   @mdl.Validator('name')
20 |   void nameValidator(val) {
21 |     if (val == null || val == '') {
22 |       throw new mdl.Invalid('empty', 'Organization name cannot be empty');
23 |     }
24 |   }
25 | 
26 |   @mdl.Attribute('user_count')
27 |   int userCount;
28 | 
29 |   Organization(ng.Http http) : super(http);
30 | 
31 |   String get url {
32 |     var url = '/organization';
33 | 
34 |     if (this.id != null) {
35 |       url += '/${this.id}';
36 |     }
37 | 
38 |     return url;
39 |   }
40 | 
41 |   void init() {
42 |     this.users = new usrs.Users(this.http);
43 |   }
44 | }
45 | 


--------------------------------------------------------------------------------
/www/dart/lib/models/server_host.dart:
--------------------------------------------------------------------------------
 1 | library server_host_mod;
 2 | 
 3 | import 'package:pritunl/model.dart' as mdl;
 4 | 
 5 | import 'package:angular/angular.dart' show Injectable;
 6 | import 'package:angular/angular.dart' as ng;
 7 | 
 8 | @Injectable()
 9 | class ServerHost extends mdl.Model {
10 |   @mdl.Attribute('id')
11 |   String id;
12 | 
13 |   @mdl.Attribute('name')
14 |   String name;
15 | 
16 |   @mdl.Attribute('server')
17 |   String server;
18 | 
19 |   @mdl.Attribute('status')
20 |   String status;
21 | 
22 |   @mdl.Attribute('address')
23 |   String address;
24 | 
25 |   ServerHost(ng.Http http) : super(http);
26 | 
27 |   String get url {
28 |     var url = '/server/${this.server}/host';
29 | 
30 |     if (this.id != null) {
31 |       url += '/${this.id}';
32 |     }
33 | 
34 |     return url;
35 |   }
36 | }
37 | 


--------------------------------------------------------------------------------
/www/dart/lib/models/server_link_output.dart:
--------------------------------------------------------------------------------
 1 | library server_link_output_mod;
 2 | 
 3 | import 'package:pritunl/model.dart' as mdl;
 4 | import 'package:pritunl/models/server.dart' as svr;
 5 | 
 6 | import 'package:angular/angular.dart' show Injectable;
 7 | import 'package:angular/angular.dart' as ng;
 8 | 
 9 | @Injectable()
10 | class ServerLinkOutput extends mdl.Model {
11 |   svr.Server server;
12 | 
13 |   @mdl.Attribute('output')
14 |   List<String> output;
15 | 
16 |   ServerLinkOutput(ng.Http http, this.server) : super(http);
17 | 
18 |   String get url {
19 |     return '/server/${this.server.id}/link_output';
20 |   }
21 | }
22 | 


--------------------------------------------------------------------------------
/www/dart/lib/models/server_org.dart:
--------------------------------------------------------------------------------
 1 | library server_org_mod;
 2 | 
 3 | import 'package:pritunl/model.dart' as mdl;
 4 | 
 5 | import 'package:angular/angular.dart' show Injectable;
 6 | import 'package:angular/angular.dart' as ng;
 7 | 
 8 | @Injectable()
 9 | class ServerOrg extends mdl.Model {
10 |   @mdl.Attribute('id')
11 |   String id;
12 | 
13 |   @mdl.Attribute('name')
14 |   String name;
15 | 
16 |   @mdl.Attribute('server')
17 |   String server;
18 | 
19 |   ServerOrg(ng.Http http) : super(http);
20 | 
21 |   String get url {
22 |     var url = '/server/${this.server}/organization';
23 | 
24 |     if (this.id != null) {
25 |       url += '/${this.id}';
26 |     }
27 | 
28 |     return url;
29 |   }
30 | }
31 | 


--------------------------------------------------------------------------------
/www/dart/lib/models/server_output.dart:
--------------------------------------------------------------------------------
 1 | library server_output_mod;
 2 | 
 3 | import 'package:pritunl/model.dart' as mdl;
 4 | import 'package:pritunl/models/server.dart' as svr;
 5 | 
 6 | import 'package:angular/angular.dart' show Injectable;
 7 | import 'package:angular/angular.dart' as ng;
 8 | 
 9 | @Injectable()
10 | class ServerOutput extends mdl.Model {
11 |   svr.Server server;
12 | 
13 |   @mdl.Attribute('output')
14 |   List<String> output;
15 | 
16 |   ServerOutput(ng.Http http, this.server) : super(http);
17 | 
18 |   String get url {
19 |     return '/server/${this.server.id}/output';
20 |   }
21 | }
22 | 


--------------------------------------------------------------------------------
/www/dart/lib/models/status.dart:
--------------------------------------------------------------------------------
 1 | library status_mod;
 2 | 
 3 | import 'package:pritunl/model.dart' as mdl;
 4 | 
 5 | import 'package:angular/angular.dart' show Injectable;
 6 | import 'package:angular/angular.dart' as ng;
 7 | 
 8 | @Injectable()
 9 | class Status extends mdl.Model {
10 |   @mdl.Attribute('org_count')
11 |   int orgCount;
12 | 
13 |   @mdl.Attribute('users_online')
14 |   int usersOnline;
15 | 
16 |   @mdl.Attribute('user_count')
17 |   int userCount;
18 | 
19 |   @mdl.Attribute('servers_online')
20 |   int serversOnline;
21 | 
22 |   @mdl.Attribute('server_count')
23 |   int serverCount;
24 | 
25 |   @mdl.Attribute('hosts_online')
26 |   int hostsOnline;
27 | 
28 |   @mdl.Attribute('host_count')
29 |   int hostCount;
30 | 
31 |   @mdl.Attribute('server_version')
32 |   String serverVersion;
33 | 
34 |   @mdl.Attribute('current_host')
35 |   String currentHost;
36 | 
37 |   @mdl.Attribute('public_ip')
38 |   String publicIp;
39 | 
40 |   @mdl.Attribute('local_networks')
41 |   List<String> localNetworks;
42 | 
43 |   @mdl.Attribute('notification')
44 |   String notification;
45 | 
46 |   Status(ng.Http http) : super(http);
47 | 
48 |   String get url {
49 |     return '/status';
50 |   }
51 | }
52 | 


--------------------------------------------------------------------------------
/www/dart/lib/pritunl.dart:
--------------------------------------------------------------------------------
1 | library pritunl;
2 | 
3 | export 'package:pritunl/transformers/sass.dart';
4 | 


--------------------------------------------------------------------------------
/www/dart/lib/routers/main.dart:
--------------------------------------------------------------------------------
 1 | library main_rout;
 2 | 
 3 | import 'package:pritunl/settings/settings.dart' as settings;
 4 | import 'package:pritunl/alert.dart' as alrt;
 5 | 
 6 | import 'package:angular/angular.dart' as ng;
 7 | 
 8 | MainRout(ng.Router router, ng.RouteViewFactory views) {
 9 |   views.configure({
10 |     'dashboard': ng.ngRoute(
11 |       path: '/dashboard',
12 |       view: 'packages/pritunl/views/dashboard.html',
13 |       enter: (_) {
14 |         alrt.clear();
15 |         settings.set('active_page', 'dashboard');
16 |       },
17 |       defaultRoute: true
18 |     ),
19 |     'users': ng.ngRoute(
20 |       path: '/users',
21 |       view: 'packages/pritunl/views/users.html',
22 |       enter: (_) {
23 |         alrt.clear();
24 |         settings.set('active_page', 'users');
25 |       }
26 |     ),
27 |     'servers': ng.ngRoute(
28 |       path: '/servers',
29 |       view: 'packages/pritunl/views/servers.html',
30 |       enter: (_) {
31 |         alrt.clear();
32 |         settings.set('active_page', 'servers');
33 |       }
34 |     )
35 |   });
36 | }
37 | 


--------------------------------------------------------------------------------
/www/dart/lib/routers/routers.dart:
--------------------------------------------------------------------------------
 1 | library routers;
 2 | 
 3 | import 'package:pritunl/routers/main.dart' as main;
 4 | 
 5 | import 'package:angular/angular.dart' as ng;
 6 | 
 7 | class RoutersMod extends ng.Module {
 8 |   RoutersMod() {
 9 |     this.bind(
10 |       ng.RouteInitializerFn,
11 |       toValue: main.MainRout
12 |     );
13 |     this.bind(
14 |       ng.NgRoutingUsePushState,
15 |       toValue: new ng.NgRoutingUsePushState.value(false)
16 |     );
17 |   }
18 | }
19 | 


--------------------------------------------------------------------------------
/www/dart/lib/settings/settings.dart:
--------------------------------------------------------------------------------
 1 | library settings;
 2 | 
 3 | var _data = {};
 4 | var _observers = {};
 5 | 
 6 | dynamic get(String name) {
 7 |   return _data[name];
 8 | }
 9 | 
10 | set(String name, dynamic value) {
11 |   _data[name] = value;
12 |   if (_observers[name] != null) {
13 |     _observers[name](name, value);
14 |   }
15 | }
16 | 
17 | void observe(String name, Function callback) {
18 |   _observers[name] = callback;
19 | }
20 | 


--------------------------------------------------------------------------------
/www/dart/lib/styles/base.scss:
--------------------------------------------------------------------------------
1 | @import 'styles/variables.scss';
2 | @import 'styles/mixins.scss';
3 | 


--------------------------------------------------------------------------------
/www/dart/lib/views/dashboard.html:
--------------------------------------------------------------------------------
1 | <x-container>
2 |   <x-status></x-status>
3 |   <x-alert-global></x-alert-global>
4 |   <x-log-entries></x-log-entries>
5 | </x-container>
6 | 


--------------------------------------------------------------------------------
/www/dart/lib/views/servers.html:
--------------------------------------------------------------------------------
1 | <x-container>
2 |   <x-servers></x-servers>
3 | </x-container>
4 | 


--------------------------------------------------------------------------------
/www/dart/lib/views/users.html:
--------------------------------------------------------------------------------
1 | <x-container>
2 |   <x-organizations></x-organizations>
3 | </x-container>
4 | 


--------------------------------------------------------------------------------
/www/dart/pubspec.yaml:
--------------------------------------------------------------------------------
 1 | name: pritunl
 2 | version: 1.0.0
 3 | dependencies:
 4 |   angular: ">=1.1.0 <2.0.0"
 5 |   web_components: ">=0.10.1"
 6 |   browser: ">=0.10.0+2"
 7 |   barback: ">=0.14.1"
 8 |   logging: ">=0.9.3"
 9 | transformers:
10 | - pritunl
11 | - angular
12 | 


--------------------------------------------------------------------------------
/www/dart/web/main.dart:
--------------------------------------------------------------------------------
 1 | library pritunl;
 2 | 
 3 | import 'package:pritunl/routers/routers.dart' as routers;
 4 | import 'package:pritunl/collections/collections.dart' as collections;
 5 | import 'package:pritunl/collections/events.dart' as evnts;
 6 | import 'package:pritunl/components/components.dart' as components;
 7 | import 'package:pritunl/decorators/decorators.dart' as decorators;
 8 | import 'package:pritunl/formatters/formatters.dart' as formatters;
 9 | import 'package:pritunl/models/models.dart' as models;
10 | import 'package:pritunl/logger.dart' as logger;
11 | 
12 | import 'package:angular/application_factory.dart' as appfactory;
13 | import 'package:angular/animate/module.dart' as animate;
14 | 
15 | void main() {
16 |   logger.setup();
17 |   var app = appfactory.applicationFactory()
18 |     .addModule(new routers.RoutersMod())
19 |     .addModule(new collections.CollectionsMod())
20 |     .addModule(new components.ComponentsMod())
21 |     .addModule(new decorators.DecoratorsMod())
22 |     .addModule(new formatters.FormattersMod())
23 |     .addModule(new models.ModelsMod())
24 |     .addModule(new animate.AnimationModule())
25 |     .run();
26 | 
27 |   app.get(evnts.Events).start();
28 | }
29 | 


--------------------------------------------------------------------------------
/www/dart/web/vendor/ace/mode-text.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/dart/web/vendor/ace/mode-text.js


--------------------------------------------------------------------------------
/www/fonts/FontAwesome.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/fonts/FontAwesome.otf


--------------------------------------------------------------------------------
/www/fonts/fontawesome-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/fonts/fontawesome-webfont.eot


--------------------------------------------------------------------------------
/www/fonts/fontawesome-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/fonts/fontawesome-webfont.ttf


--------------------------------------------------------------------------------
/www/fonts/fontawesome-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/fonts/fontawesome-webfont.woff


--------------------------------------------------------------------------------
/www/fonts/fontawesome-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/fonts/fontawesome-webfont.woff2


--------------------------------------------------------------------------------
/www/fonts/fredoka-one.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/fonts/fredoka-one.eot


--------------------------------------------------------------------------------
/www/fonts/fredoka-one.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/fonts/fredoka-one.woff


--------------------------------------------------------------------------------
/www/fonts/glyphicons-halflings-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/fonts/glyphicons-halflings-regular.eot


--------------------------------------------------------------------------------
/www/fonts/glyphicons-halflings-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/fonts/glyphicons-halflings-regular.ttf


--------------------------------------------------------------------------------
/www/fonts/glyphicons-halflings-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/fonts/glyphicons-halflings-regular.woff


--------------------------------------------------------------------------------
/www/fonts/ubuntu-bold.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/fonts/ubuntu-bold.eot


--------------------------------------------------------------------------------
/www/fonts/ubuntu-bold.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/fonts/ubuntu-bold.woff


--------------------------------------------------------------------------------
/www/fonts/ubuntu.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/fonts/ubuntu.eot


--------------------------------------------------------------------------------
/www/fonts/ubuntu.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/fonts/ubuntu.woff


--------------------------------------------------------------------------------
/www/img/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/img/favicon.ico


--------------------------------------------------------------------------------
/www/img/header_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/img/header_logo.png


--------------------------------------------------------------------------------
/www/img/header_logo.xcf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/img/header_logo.xcf


--------------------------------------------------------------------------------
/www/img/logo100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/img/logo100.png


--------------------------------------------------------------------------------
/www/img/logo14.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/img/logo14.png


--------------------------------------------------------------------------------
/www/img/logo140.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/img/logo140.png


--------------------------------------------------------------------------------
/www/img/logo16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/img/logo16.png


--------------------------------------------------------------------------------
/www/img/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/img/logo192.png


--------------------------------------------------------------------------------
/www/img/logo256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/img/logo256.png


--------------------------------------------------------------------------------
/www/img/logo32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/img/logo32.png


--------------------------------------------------------------------------------
/www/img/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/img/logo512.png


--------------------------------------------------------------------------------
/www/img/logo64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/img/logo64.png


--------------------------------------------------------------------------------
/www/img/logo_code.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/img/logo_code.png


--------------------------------------------------------------------------------
/www/img/logo_full.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/img/logo_full.png


--------------------------------------------------------------------------------
/www/img/logo_full.xcf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/img/logo_full.xcf


--------------------------------------------------------------------------------
/www/img/logo_full2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/img/logo_full2.png


--------------------------------------------------------------------------------
/www/img/logo_full2.xcf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/img/logo_full2.xcf


--------------------------------------------------------------------------------
/www/img/logo_full3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/img/logo_full3.png


--------------------------------------------------------------------------------
/www/img/logo_full3.xcf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/img/logo_full3.xcf


--------------------------------------------------------------------------------
/www/img/logo_stripe.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/img/logo_stripe.png


--------------------------------------------------------------------------------
/www/init/demo.js:
--------------------------------------------------------------------------------
 1 | /* jshint -W098:true */
 2 | define([
 3 |   'jquery',
 4 |   'underscore',
 5 |   'backbone',
 6 |   'demo/ajax'
 7 | ], function($, _, Backbone, demoAjax) {
 8 |   'use strict';
 9 |   var initialize = function() {
10 |     window.demo = true;
11 |     Backbone.ajax = demoAjax;
12 |   };
13 | 
14 |   return initialize;
15 | });
16 | 


--------------------------------------------------------------------------------
/www/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/logo.png


--------------------------------------------------------------------------------
/www/models/admin.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone'
 5 | ], function($, _, Backbone) {
 6 |   'use strict';
 7 |   var AdminModel = Backbone.Model.extend({
 8 |     defaults: {
 9 |       'id': null,
10 |       'username': null,
11 |       'yubikey_id': null,
12 |       'super_user': null,
13 |       'auth_api': null,
14 |       'token': null,
15 |       'secret': null,
16 |       'otp_auth': null,
17 |       'otp_secret': null,
18 |       'audit': null
19 |     },
20 |     url: function() {
21 |       var url = '/admin';
22 | 
23 |       if (this.get('id')) {
24 |         url += '/' + this.get('id');
25 |       }
26 | 
27 |       return url;
28 |     },
29 |     destroyOtpSecret: function(options) {
30 |       var otpSecret = this.get('otp_secret');
31 |       this.save({
32 |         otp_secret: true
33 |       }, options);
34 |       this.set({'otp_secret': otpSecret});
35 |     }
36 |   });
37 | 
38 |   return AdminModel;
39 | });
40 | 


--------------------------------------------------------------------------------
/www/models/authSession.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone'
 5 | ], function($, _, Backbone) {
 6 |   'use strict';
 7 |   var AuthSessionModel = Backbone.Model.extend({
 8 |     defaults: {
 9 |       'authenticated': null,
10 |       'username': null,
11 |       'password': null,
12 |       'default': null
13 |     },
14 |     url: function() {
15 |       return '/auth/session';
16 |     }
17 |   });
18 | 
19 |   return AuthSessionModel;
20 | });
21 | 


--------------------------------------------------------------------------------
/www/models/device.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone'
 5 | ], function($, _, Backbone) {
 6 |   'use strict';
 7 |   var DeviceModel = Backbone.Model.extend({
 8 |     defaults: {
 9 |       'id': null,
10 |       'org_id': null,
11 |       'user_id': null,
12 |       'user_name': null,
13 |       'name': null,
14 |       'platform': null,
15 |       'reg_key': null
16 |     },
17 |     url: function() {
18 |       return '/device/register/' + this.get('org_id') + '/' +
19 |         this.get('user_id') + '/' + this.get('id');
20 |     }
21 |   });
22 | 
23 |   return DeviceModel;
24 | });
25 | 


--------------------------------------------------------------------------------
/www/models/event.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone'
 5 | ], function($, _, Backbone) {
 6 |   'use strict';
 7 |   var EventModel = Backbone.Model.extend({
 8 |     defaults: {
 9 |       'id': null,
10 |       'type': null,
11 |       'resource_id': null,
12 |       'timestamp': null
13 |     }
14 |   });
15 | 
16 |   return EventModel;
17 | });
18 | 


--------------------------------------------------------------------------------
/www/models/host.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone'
 5 | ], function($, _, Backbone) {
 6 |   'use strict';
 7 |   var HostModel = Backbone.Model.extend({
 8 |     defaults: {
 9 |       'name': null,
10 |       'hostname': null,
11 |       'instance_id': null,
12 |       'status': null,
13 |       'uptime': null,
14 |       'version': null,
15 |       'user_count': null,
16 |       'users_online': null,
17 |       'public_address': null,
18 |       'public_addr': null,
19 |       'public_address6': null,
20 |       'public_addr6': null,
21 |       'routed_subnet6': null,
22 |       'routed_subnet6_wg': null,
23 |       'proxy_ndp': null,
24 |       'local_address': null,
25 |       'local_addr': null,
26 |       'local_address6': null,
27 |       'local_addr6': null,
28 |       'link_address': null,
29 |       'availability_group': null
30 |     },
31 |     url: function() {
32 |       var url = '/host';
33 | 
34 |       if (this.get('id')) {
35 |         url += '/' + this.get('id');
36 |       }
37 | 
38 |       return url;
39 |     }
40 |   });
41 | 
42 |   return HostModel;
43 | });
44 | 


--------------------------------------------------------------------------------
/www/models/hostUsage.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone'
 5 | ], function($, _, Backbone) {
 6 |   'use strict';
 7 |   var HostUsageModel = Backbone.Model.extend({
 8 |     defaults: {
 9 |       'cpu': null,
10 |       'mem': null
11 |     },
12 |     url: function() {
13 |       return '/host/' + this.get('id') + '/usage/' + this.getPeriod();
14 |     },
15 |     getPeriod: function() {
16 |       return this.period;
17 |     },
18 |     setPeriod: function(period) {
19 |       this.period = period;
20 |     },
21 |     getGraphData: function(type) {
22 |       var i;
23 |       var points = [];
24 |       var data = this.get(type);
25 |       if (!data) {
26 |         return null;
27 |       }
28 |       for (i = 0; i < data.length; i++) {
29 |         points.push({x: data[i][0], y: data[i][1]});
30 |       }
31 |       return points;
32 |     }
33 |   });
34 | 
35 |   return HostUsageModel;
36 | });
37 | 


--------------------------------------------------------------------------------
/www/models/key.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone'
 5 | ], function($, _, Backbone) {
 6 |   'use strict';
 7 |   var KeyModel = Backbone.Model.extend({
 8 |     defaults: {
 9 |       'id': null,
10 |       'key_url': null,
11 |       'key_zip_url': null,
12 |       'key_onc_url': null,
13 |       'view_url': null,
14 |       'uri_url': null
15 |     },
16 |     url: function() {
17 |       return '/key/' + this.get('organization') + '/' + this.get('user');
18 |     }
19 |   });
20 | 
21 |   return KeyModel;
22 | });
23 | 


--------------------------------------------------------------------------------
/www/models/link.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone'
 5 | ], function($, _, Backbone) {
 6 |   'use strict';
 7 |   var LinkModel = Backbone.Model.extend({
 8 |     defaults: {
 9 |       'id': null,
10 |       'name': null,
11 |       'type': null,
12 |       'ipv6': null,
13 |       'host_check': null,
14 |       'action': null,
15 |       'status': null,
16 |       'locations': null,
17 |       'timeout': null,
18 |       'preferred_ike': null,
19 |       'preferred_esp': null,
20 |       'force_preferred': null
21 |     },
22 |     url: function() {
23 |       var url = '/link';
24 | 
25 |       if (this.get('id')) {
26 |         url += '/' + this.get('id');
27 |       }
28 | 
29 |       return url;
30 |     }
31 |   });
32 | 
33 |   return LinkModel;
34 | });
35 | 


--------------------------------------------------------------------------------
/www/models/linkHost.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone'
 5 | ], function($, _, Backbone) {
 6 |   'use strict';
 7 |   var LinkHostModel = Backbone.Model.extend({
 8 |     defaults: {
 9 |       'id': null,
10 |       'link_id': null,
11 |       'location_id': null,
12 |       'name': null,
13 |       'timeout': null,
14 |       'priority': null,
15 |       'backoff': null,
16 |       'static': null,
17 |       'public_address': null,
18 |       'local_address': null,
19 |       'address6': null,
20 |       'version': null
21 |     },
22 |     url: function() {
23 |       var url = '/link/' + this.get('link_id') + '/location/' +
24 |         this.get('location_id') + '/host';
25 | 
26 |       if (this.get('id')) {
27 |         url += '/' + this.get('id');
28 |       }
29 | 
30 |       return url;
31 |     }
32 |   });
33 | 
34 |   return LinkHostModel;
35 | });
36 | 


--------------------------------------------------------------------------------
/www/models/linkHostConf.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone'
 5 | ], function($, _, Backbone) {
 6 |   'use strict';
 7 |   var LinkHostConfModel = Backbone.Model.extend({
 8 |     defaults: {
 9 |       'id': null,
10 |       'name': null,
11 |       'hostname': null,
12 |       'conf': null,
13 |       'ubnt_conf': null
14 |     },
15 |     url: function() {
16 |       return '/link/' + this.get('link_id') + '/location/' +
17 |         this.get('location_id') + '/host/' + this.get('id') + '/conf';
18 |     }
19 |   });
20 | 
21 |   return LinkHostConfModel;
22 | });
23 | 


--------------------------------------------------------------------------------
/www/models/linkHostUri.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone'
 5 | ], function($, _, Backbone) {
 6 |   'use strict';
 7 |   var LinkHostUriModel = Backbone.Model.extend({
 8 |     defaults: {
 9 |       'id': null,
10 |       'name': null,
11 |       'hostname': null,
12 |       'uri': null
13 |     },
14 |     url: function() {
15 |       return '/link/' + this.get('link_id') + '/location/' +
16 |         this.get('location_id') + '/host/' + this.get('id') + '/uri';
17 |     }
18 |   });
19 | 
20 |   return LinkHostUriModel;
21 | });
22 | 


--------------------------------------------------------------------------------
/www/models/linkLocation.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone'
 5 | ], function($, _, Backbone) {
 6 |   'use strict';
 7 |   var LinkLocationModel = Backbone.Model.extend({
 8 |     defaults: {
 9 |       'id': null,
10 |       'link_id': null,
11 |       'link_type': null,
12 |       'type': null,
13 |       'ipv6': null,
14 |       'name': null,
15 |       'status': null,
16 |       'location': null,
17 |       'hosts': null,
18 |       'routes': null,
19 |       'peers': null
20 |     },
21 |     url: function() {
22 |       var url = '/link/' + this.get('link_id') + '/location';
23 | 
24 |       if (this.get('id')) {
25 |         url += '/' + this.get('id');
26 |       }
27 | 
28 |       return url;
29 |     }
30 |   });
31 | 
32 |   return LinkLocationModel;
33 | });
34 | 


--------------------------------------------------------------------------------
/www/models/linkPeer.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone'
 5 | ], function($, _, Backbone) {
 6 |   'use strict';
 7 |   var LinkPeerModel = Backbone.Model.extend({
 8 |     defaults: {
 9 |       'id': null,
10 |       'link_id': null,
11 |       'location_id': null,
12 |       'name': null,
13 |       'status': null
14 |     },
15 |     url: function() {
16 |       var url = '/link/' + this.get('link_id') + '/location/' +
17 |         this.get('location_id') + '/peer';
18 | 
19 |       if (this.get('id')) {
20 |         url += '/' + this.get('id');
21 |       }
22 | 
23 |       return url;
24 |     }
25 |   });
26 | 
27 |   return LinkPeerModel;
28 | });
29 | 


--------------------------------------------------------------------------------
/www/models/linkRoute.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone'
 5 | ], function($, _, Backbone) {
 6 |   'use strict';
 7 |   var LinkRouteModel = Backbone.Model.extend({
 8 |     defaults: {
 9 |       'id': null,
10 |       'link_id': null,
11 |       'location_id': null
12 |     },
13 |     url: function() {
14 |       var url = '/link/' + this.get('link_id') + '/location/' +
15 |         this.get('location_id') + '/route';
16 | 
17 |       if (this.get('id')) {
18 |         url += '/' + this.get('id');
19 |       }
20 | 
21 |       return url;
22 |     }
23 |   });
24 | 
25 |   return LinkRouteModel;
26 | });
27 | 


--------------------------------------------------------------------------------
/www/models/linkRouteExclude.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone'
 5 | ], function($, _, Backbone) {
 6 |   'use strict';
 7 |   var LinkRouteModel = Backbone.Model.extend({
 8 |     defaults: {
 9 |       'id': null,
10 |       'link_id': null,
11 |       'location_id': null
12 |     },
13 |     url: function() {
14 |       var url = '/link/' + this.get('link_id') + '/location/' +
15 |         this.get('location_id') + '/route_exclude';
16 | 
17 |       if (this.get('id')) {
18 |         url += '/' + this.get('id');
19 |       }
20 | 
21 |       return url;
22 |     }
23 |   });
24 | 
25 |   return LinkRouteModel;
26 | });
27 | 


--------------------------------------------------------------------------------
/www/models/linkTransit.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone'
 5 | ], function($, _, Backbone) {
 6 |   'use strict';
 7 |   var LinkTransitModel = Backbone.Model.extend({
 8 |     defaults: {
 9 |       'id': null,
10 |       'link_id': null,
11 |       'location_id': null,
12 |       'transit_id': null,
13 |       'name': null
14 |     },
15 |     url: function() {
16 |       var url = '/link/' + this.get('link_id') + '/location/' +
17 |         this.get('location_id') + '/transit';
18 | 
19 |       if (this.get('id')) {
20 |         url += '/' + this.get('id');
21 |       }
22 | 
23 |       return url;
24 |     }
25 |   });
26 | 
27 |   return LinkTransitModel;
28 | });
29 | 


--------------------------------------------------------------------------------
/www/models/log.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone'
 5 | ], function($, _, Backbone) {
 6 |   'use strict';
 7 |   var LogModel = Backbone.Model.extend({
 8 |     defaults: {
 9 |       'id': null,
10 |       'timestamp': null,
11 |       'message': null
12 |     },
13 |     url: function() {
14 |       var url = '/log';
15 | 
16 |       if (this.get('id')) {
17 |         url += '/' + this.get('id');
18 |       }
19 | 
20 |       return url;
21 |     }
22 |   });
23 | 
24 |   return LogModel;
25 | });
26 | 


--------------------------------------------------------------------------------
/www/models/logs.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone'
 5 | ], function($, _, Backbone) {
 6 |   'use strict';
 7 |   var LogsModel = Backbone.Model.extend({
 8 |     defaults: {
 9 |       'output': null
10 |     },
11 |     url: function() {
12 |       return '/logs';
13 |     }
14 |   });
15 | 
16 |   return LogsModel;
17 | });
18 | 


--------------------------------------------------------------------------------
/www/models/org.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone'
 5 | ], function($, _, Backbone) {
 6 |   'use strict';
 7 |   var OrgModel = Backbone.Model.extend({
 8 |     defaults: {
 9 |       'id': null,
10 |       'name': null,
11 |       'user_count': null
12 |     },
13 |     url: function() {
14 |       var url = '/organization';
15 | 
16 |       if (this.get('id')) {
17 |         url += '/' + this.get('id');
18 |       }
19 | 
20 |       return url;
21 |     }
22 |   });
23 | 
24 |   return OrgModel;
25 | });
26 | 


--------------------------------------------------------------------------------
/www/models/serverBandwidth.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone'
 5 | ], function($, _, Backbone) {
 6 |   'use strict';
 7 |   var ServerBandwidthModel = Backbone.Model.extend({
 8 |     defaults: {
 9 |       'received': null,
10 |       'sent': null
11 |     },
12 |     url: function() {
13 |       return '/server/' + this.get('id') + '/bandwidth/' + this.getPeriod();
14 |     },
15 |     getPeriod: function() {
16 |       return this.period;
17 |     },
18 |     setPeriod: function(period) {
19 |       this.period = period;
20 |     },
21 |     getGraphData: function(type) {
22 |       var i;
23 |       var points = [];
24 |       var data = this.get(type);
25 |       if (!data) {
26 |         return null;
27 |       }
28 |       var max = 0;
29 |       for (i = 0; i < data.length; i++) {
30 |         max = Math.max(data[i][1], max);
31 |         points.push({x: data[i][0], y: data[i][1]});
32 |       }
33 |       return {
34 |         'max': max,
35 |         'points': points
36 |       };
37 |     }
38 |   });
39 | 
40 |   return ServerBandwidthModel;
41 | });
42 | 


--------------------------------------------------------------------------------
/www/models/serverHost.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone'
 5 | ], function($, _, Backbone) {
 6 |   'use strict';
 7 |   var ServerHostModel = Backbone.Model.extend({
 8 |     defaults: {
 9 |       'id': null,
10 |       'server': null,
11 |       'name': null,
12 |       'address': null
13 |     },
14 |     url: function() {
15 |       var url = '/server/' + this.get('server') + '/host';
16 | 
17 |       if (this.get('id')) {
18 |         url += '/' + this.get('id');
19 |       }
20 | 
21 |       return url;
22 |     }
23 |   });
24 | 
25 |   return ServerHostModel;
26 | });
27 | 


--------------------------------------------------------------------------------
/www/models/serverLink.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone'
 5 | ], function($, _, Backbone) {
 6 |   'use strict';
 7 |   var ServerLinkModel = Backbone.Model.extend({
 8 |     defaults: {
 9 |       'id': null,
10 |       'server': null,
11 |       'name': null,
12 |       'use_local_address': null
13 |     },
14 |     url: function() {
15 |       var url = '/server/' + this.get('server') + '/link';
16 | 
17 |       if (this.get('id')) {
18 |         url += '/' + this.get('id');
19 |       }
20 | 
21 |       return url;
22 |     }
23 |   });
24 | 
25 |   return ServerLinkModel;
26 | });
27 | 


--------------------------------------------------------------------------------
/www/models/serverOrg.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone'
 5 | ], function($, _, Backbone) {
 6 |   'use strict';
 7 |   var ServerOrgModel = Backbone.Model.extend({
 8 |     defaults: {
 9 |       'id': null,
10 |       'server': null,
11 |       'name': null
12 |     },
13 |     url: function() {
14 |       var url = '/server/' + this.get('server') + '/organization';
15 | 
16 |       if (this.get('id')) {
17 |         url += '/' + this.get('id');
18 |       }
19 | 
20 |       return url;
21 |     }
22 |   });
23 | 
24 |   return ServerOrgModel;
25 | });
26 | 


--------------------------------------------------------------------------------
/www/models/serverOutput.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone'
 5 | ], function($, _, Backbone) {
 6 |   'use strict';
 7 |   var ServerOutputModel = Backbone.Model.extend({
 8 |     defaults: {
 9 |       'id': null,
10 |       'output': null
11 |     },
12 |     url: function() {
13 |       return '/server/' + this.get('id') + '/output';
14 |     }
15 |   });
16 | 
17 |   return ServerOutputModel;
18 | });
19 | 


--------------------------------------------------------------------------------
/www/models/serverOutputLink.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone'
 5 | ], function($, _, Backbone) {
 6 |   'use strict';
 7 |   var ServerOutputLinkModel = Backbone.Model.extend({
 8 |     defaults: {
 9 |       'id': null,
10 |       'output': null
11 |     },
12 |     url: function() {
13 |       return '/server/' + this.get('id') + '/link_output';
14 |     }
15 |   });
16 | 
17 |   return ServerOutputLinkModel;
18 | });
19 | 


--------------------------------------------------------------------------------
/www/models/serverRoute.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone'
 5 | ], function($, _, Backbone) {
 6 |   'use strict';
 7 |   var ServerRouteModel = Backbone.Model.extend({
 8 |     defaults: {
 9 |       'id': null,
10 |       'server': null,
11 |       'network': null,
12 |       'comment': null,
13 |       'metric': null,
14 |       'virtual_network': null,
15 |       'wg_network': null,
16 |       'network_link': null,
17 |       'server_link': null,
18 |       'nat': null,
19 |       'nat_interface': null,
20 |       'nat_netmap': null,
21 |       'net_gateway': null,
22 |       'advertise': null,
23 |       'vpc_region': null,
24 |       'vpc_id': null
25 |     },
26 |     url: function() {
27 |       var url = '/server/' + this.get('server') + '/route';
28 | 
29 |       if (this.get('id')) {
30 |         url += '/' + this.get('id');
31 |       }
32 | 
33 |       return url;
34 |     }
35 |   });
36 | 
37 |   return ServerRouteModel;
38 | });
39 | 


--------------------------------------------------------------------------------
/www/models/state.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone'
 5 | ], function($, _, Backbone) {
 6 |   'use strict';
 7 |   var StateModel = Backbone.Model.extend({
 8 |     defaults: {
 9 |       'super_user': null,
10 |       'csrf_token': null,
11 |       'theme': null,
12 |       'active': null,
13 |       'plan': null,
14 |       'version': null,
15 |       'sso': null
16 |     },
17 |     url: function() {
18 |       return '/state';
19 |     }
20 |   });
21 | 
22 |   return StateModel;
23 | });
24 | 


--------------------------------------------------------------------------------
/www/models/status.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone'
 5 | ], function($, _, Backbone) {
 6 |   'use strict';
 7 |   var StatusModel = Backbone.Model.extend({
 8 |     defaults: {
 9 |       'org_count': null,
10 |       'users_online': null,
11 |       'user_count': null,
12 |       'servers_online': null,
13 |       'server_count': null,
14 |       'server_version': null,
15 |       'public_ip': null,
16 |       'local_networks': null,
17 |       'notification': null
18 |     },
19 |     url: function() {
20 |       return '/status';
21 |     }
22 |   });
23 | 
24 |   return StatusModel;
25 | });
26 | 


--------------------------------------------------------------------------------
/www/models/userAudit.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone'
 5 | ], function($, _, Backbone) {
 6 |   'use strict';
 7 |   var UserAuditModel = Backbone.Model.extend({
 8 |     defaults: {
 9 |       'id': null,
10 |       'user_id': null,
11 |       'org_id': null,
12 |       'timestamp': null,
13 |       'type': null,
14 |       'remote_addr': null,
15 |       'message': null
16 |     },
17 |     url: function() {
18 |       return null;
19 |     }
20 |   });
21 | 
22 |   return UserAuditModel;
23 | });
24 | 


--------------------------------------------------------------------------------
/www/models/userBulk.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone'
 5 | ], function($, _, Backbone) {
 6 |   'use strict';
 7 |   var UserBulkModel = Backbone.Model.extend({
 8 |     defaults: {
 9 |       'organization': null,
10 |       'users': null
11 |     },
12 |     initialize: function() {
13 |       this.set({'users': []});
14 |     },
15 |     url: function() {
16 |       return '/user/' + this.get('organization') + '/multi';
17 |     },
18 |     toJSON: function() {
19 |       return this.get('users');
20 |     },
21 |     addUser: function(name, email) {
22 |       var users = this.get('users');
23 |       users.push({
24 |         'name': name,
25 |         'email': email || null,
26 |       });
27 |     }
28 |   });
29 | 
30 |   return UserBulkModel;
31 | });
32 | 


--------------------------------------------------------------------------------
/www/models/userDevice.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone'
 5 | ], function($, _, Backbone) {
 6 |   'use strict';
 7 |   var UserDeviceModel = Backbone.Model.extend({
 8 |     defaults: {
 9 |       'id': null,
10 |       'user_id': null,
11 |       'org_id': null,
12 |       'name': null,
13 |       'registered': null,
14 |       'timestamp': null
15 |     },
16 |     url: function() {
17 |       return '/user/' + this.get('org_id') + '/' + this.get('user_id') +
18 |         '/device/' + this.get('id');
19 |     }
20 |   });
21 | 
22 |   return UserDeviceModel;
23 | });
24 | 


--------------------------------------------------------------------------------
/www/models/userServer.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone'
 5 | ], function($, _, Backbone) {
 6 |   'use strict';
 7 |   var UserServerModel = Backbone.Model.extend({
 8 |     defaults: {
 9 |       'id': null,
10 |       'name': null,
11 |       'status': null,
12 |       'server_id': null,
13 |       'device_id': null,
14 |       'device_name': null,
15 |       'platform': null,
16 |       'real_address': null,
17 |       'virt_address': null,
18 |       'connected_since': null
19 |     }
20 |   });
21 | 
22 |   return UserServerModel;
23 | });
24 | 


--------------------------------------------------------------------------------
/www/models/zones.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone'
 5 | ], function($, _, Backbone) {
 6 |   'use strict';
 7 |   var ZonesModel = Backbone.Model.extend({
 8 |     defaults: {
 9 |       'us-east-1': [],
10 |       'us-east-2': [],
11 |       'us-west-1': [],
12 |       'us-west-2': [],
13 |       'us-gov-east-1': [],
14 |       'us-gov-west-1': [],
15 |       'eu-north-1': [],
16 |       'eu-west-1': [],
17 |       'eu-west-2': [],
18 |       'eu-west-3': [],
19 |       'eu-central-1': [],
20 |       'ca-central-1': [],
21 |       'cn-north-1': [],
22 |       'cn-northwest-1': [],
23 |       'ap-northeast-1': [],
24 |       'ap-northeast-2': [],
25 |       'ap-southeast-1': [],
26 |       'ap-southeast-2': [],
27 |       'ap-east-1': [],
28 |       'ap-south-1': [],
29 |       'sa-east-1': []
30 |     },
31 |     url: '/settings/zones'
32 |   });
33 | 
34 |   return ZonesModel;
35 | });
36 | 


--------------------------------------------------------------------------------
/www/package.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "name": "pritunl.js",
 3 |   "dependencies": {
 4 |     "grunt": "0.4.5",
 5 |     "grunt-contrib-clean": "0.5.0",
 6 |     "grunt-contrib-copy": "0.4.1",
 7 |     "grunt-contrib-jshint": "0.6.0",
 8 |     "grunt-contrib-requirejs": "0.4.1"
 9 |   }
10 | }
11 | 


--------------------------------------------------------------------------------
/www/root/robots.txt:
--------------------------------------------------------------------------------
1 | User-agent: *
2 | Disallow: /
3 | 


--------------------------------------------------------------------------------
/www/templates/admins.html:
--------------------------------------------------------------------------------
 1 | <div class="admins-list">
 2 |   <div class="admins-list-header">
 3 |     <h1 class="admins-title title">Administrators</h1>
 4 |     <div class="admins-list-buttons">
 5 |       <button type="button" class="header-button admins-del-selected btn btn-danger" disabled>Delete Selected</button>
 6 |       <button type="button" class="header-button admins-add-admin btn btn-primary">Add Administrator</button>
 7 |     </div>
 8 |   </div>
 9 |   <div class="alerts-container"></div>
10 |   <div class="admins-container">
11 |     <div class="admins-list-header">
12 |       <div class="label label-warning toggle-hidden no-select">Administrators</div>
13 |     </div>
14 |   </div>
15 | </div>
16 | 


--------------------------------------------------------------------------------
/www/templates/adminsList.html:
--------------------------------------------------------------------------------
1 | <div class="loading">
2 |   Loading...
3 | </div>
4 | 


--------------------------------------------------------------------------------
/www/templates/adminsListItem.html:
--------------------------------------------------------------------------------
 1 | <div class="admin layout-horizontal">
 2 |   <div class="selector no-select">
 3 |     <span class="selector-inner glyphicon glyphicon-ok"></span>
 4 |   </div>
 5 |   <div class="name-container layout-flex">
 6 |     <span class="name-icon glyphicon glyphicon-user"></span>
 7 |     <a class="admin-username title no-select" data-toggle="tooltip" title="Click to modify this administrator"><%- username %></a>
 8 |     <span class="admin-id title">(<%- id %>)</span>
 9 |   </div>
10 |   <div class="right-container">
11 |     <a class="get-otp-auth glyphicon glyphicon-qrcode no-select <%- otp_auth ? '' : 'no-otp-auth' %>" data-toggle="tooltip" title="Get two-step authentication key"></a>
12 |     <a class="audit-admin glyphicon glyphicon-list-alt no-select <%- audit ? '' : 'no-audit-admin' %>" data-toggle="tooltip" title="Administrator audit"></a>
13 |     <a class="disable-admin glyphicon glyphicon glyphicon-ban-circle no-select" data-toggle="tooltip" title="Disable and logout administrator"></a>
14 |     <a class="enable-admin glyphicon glyphicon glyphicon-ok-circle no-select" data-toggle="tooltip" title="Enable administrator"></a>
15 |   </div>
16 | </div>
17 | 


--------------------------------------------------------------------------------
/www/templates/alert.html:
--------------------------------------------------------------------------------
1 | <div class="alert alert-<%- type %> <%- (dismissable) ? 'alert-dismissable' : '' %>">
2 |   <% if (dismissable) { %>
3 |     <button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
4 |   <% } %>
5 |   <span>
6 |     <%= message %>
7 |   </span>
8 | </div>
9 | 


--------------------------------------------------------------------------------
/www/templates/dashboard.html:
--------------------------------------------------------------------------------
1 | <div class="alerts-container"></div>
2 | 


--------------------------------------------------------------------------------
/www/templates/dashboardLog.html:
--------------------------------------------------------------------------------
1 | <h2 class="log-title title">
2 |   Recent log entries
3 | </h2>
4 | <div class="log-entry-list"></div>
5 | 


--------------------------------------------------------------------------------
/www/templates/dashboardLogItem.html:
--------------------------------------------------------------------------------
1 | <span class="log-icon glyphicon glyphicon-record"></span>
2 | <span class="log-msg">
3 |   <%- message %>
4 | </span>
5 | <span class="log-time">
6 |   <%- window.formatTime(timestamp) %>
7 | </span>
8 | 


--------------------------------------------------------------------------------
/www/templates/devicesList.html:
--------------------------------------------------------------------------------
 1 | <div class="devices-list">
 2 |   <div class="devices-list-header">
 3 |     <div class="label label-success toggle-hidden no-select">Devices</div><h2 class="devices-list-title title">Devices Pending Registration</h2>
 4 |   </div>
 5 |   <div class="devices-list-container">
 6 |     <div class="no-devices">
 7 |       There are no pending devices.
 8 |     </div>
 9 |   </div>
10 | </div>
11 | 


--------------------------------------------------------------------------------
/www/templates/devicesListItem.html:
--------------------------------------------------------------------------------
 1 | <div class="devices-device">
 2 |   <div class="name-container">
 3 |     <span class="name-icon glyphicon glyphicon-tasks"></span>
 4 |     <span class="device-name title"><%- user_name + ' - ' + name %></span>
 5 |   </div>
 6 |   <div class="button-container">
 7 |     <button type="button" class="devices-device-reg btn btn-primary btn-xs">Register Device</button>
 8 |     <button type="button" class="devices-device-del btn btn-danger btn-xs">Remove Device</button>
 9 |   </div>
10 | </div>
11 | 


--------------------------------------------------------------------------------
/www/templates/hostUsage.html:
--------------------------------------------------------------------------------
1 | <div class="host-graph-cpu"></div>
2 | <div class="host-graph-mem"></div>
3 | 


--------------------------------------------------------------------------------
/www/templates/hostsList.html:
--------------------------------------------------------------------------------
 1 | <div class="hosts-list-header">
 2 |   <h1 class="hosts-list-title title">Hosts</h1>
 3 |   <div class="hosts-list-buttons">
 4 |   </div>
 5 | </div>
 6 | <div class="alerts-container"></div>
 7 | <div class="hosts-list-container">
 8 | </div>
 9 | <button type="button" class="prev-page btn btn-primary btn-sm">Previous Page</button>
10 | <button type="button" class="next-page btn btn-primary btn-sm">Next Page</button>
11 | <div class="pages no-select">
12 |   <div class="links">
13 |     <a class="link first">First</a>
14 |     <a class="link last">Last</a>
15 |   </div>
16 | </div>
17 | 


--------------------------------------------------------------------------------
/www/templates/linkLocationsList.html:
--------------------------------------------------------------------------------
1 | <div class="no-locations">
2 |   There are no locations on this link.
3 | </div>
4 | 


--------------------------------------------------------------------------------
/www/templates/linksList.html:
--------------------------------------------------------------------------------
 1 | <div class="links-upgrade">
 2 |   Upgrade to Enterprise+ for site-to-site links with IPsec
 3 | </div>
 4 | <div class="links-list">
 5 |   <div class="links-list-header">
 6 |     <h1 class="links-list-title title">Links</h1>
 7 |     <div class="links-list-buttons">
 8 |       <button type="button" class="header-button links-add-link btn btn-primary">Add Link</button>
 9 |       <button type="button" class="header-button links-add-location btn btn-primary">Add Location</button>
10 |     </div>
11 |   </div>
12 |   <div class="alerts-container"></div>
13 |   <div class="links-list-container">
14 |     <div class="no-links">
15 |       There are no links on this system.
16 |     </div>
17 |   </div>
18 |   <button type="button" class="prev-page btn btn-primary btn-sm">Previous Page</button>
19 |   <button type="button" class="next-page btn btn-primary btn-sm">Next Page</button>
20 |   <div class="pages no-select">
21 |     <div class="page-links">
22 |       <a class="page-link first">First</a>
23 |       <a class="page-link last">Last</a>
24 |     </div>
25 |   </div>
26 | </div>
27 | 


--------------------------------------------------------------------------------
/www/templates/linksListItem.html:
--------------------------------------------------------------------------------
1 | <div class="link-header">
2 |   <div class="link-label label label-purple toggle-hidden no-select"><%- (type === 'direct' ? 'Direct' : 'Site-To-Site') + ' Link' %></div><h2 class="link-title title"><a class="no-select" data-toggle="tooltip" title="Click to open link settings"></a><span class="link-id title">(<%- id %>)</span></h2>
3 |   <button type="button" class="link-del btn btn-danger btn-sm no-select">Delete Link</button>
4 |   <button type="button" class="link-stop btn btn-warning btn-sm no-select">Stop Link</button>
5 |   <button type="button" class="link-start btn btn-success btn-sm no-select">Start Link</button>
6 |   <button type="button" class="link-rekey btn btn-primary btn-sm no-select">Rekey Link</button>
7 | </div>
8 | 


--------------------------------------------------------------------------------
/www/templates/modal.html:
--------------------------------------------------------------------------------
 1 | <div class="modal fade" tabindex="-1" role="dialog" aria-hidden="true">
 2 |   <div class="modal-dialog">
 3 |     <div class="modal-content">
 4 |       <div class="modal-header">
 5 |         <button type="button" class="close" aria-hidden="true">&times;</button>
 6 |         <h4 class="modal-title title"><%- title %></h4>
 7 |         <div class="modal-advanced-toggle no-select">Advanced</div>
 8 |       </div>
 9 |       <div class="modal-body"></div>
10 |       <div class="modal-footer">
11 |         <% if (cancelText !== null) { %>
12 |           <button type="button" class="btn btn-default cancel"><%- cancelText %></button>
13 |         <% } %>
14 |         <% if (okText !== null) { %>
15 |           <button type="button" class="btn btn-primary ok"><%- okText %></button>
16 |         <% } %>
17 |       </div>
18 |     </div>
19 |   </div>
20 | </div>
21 | 


--------------------------------------------------------------------------------
/www/templates/modalAddLocPeer.html:
--------------------------------------------------------------------------------
 1 | <div class="form-group">
 2 |   <div class="form-group peer-id">
 3 |     <label>Peer Location</label>
 4 |     <select class="form-control" data-toggle="tooltip" title="Select location to peer">
 5 |       <% _.each(locations, function(location) { %>
 6 |       <% if (location.id !== location_id) { %>
 7 |       <option value="<%- location.id %>"><%- location.name %></option>
 8 |       <% } %>
 9 |       <% }); %>
10 |     </select>
11 |   </div>
12 | </div>
13 | 


--------------------------------------------------------------------------------
/www/templates/modalAddLocRoute.html:
--------------------------------------------------------------------------------
1 | <div class="form-group">
2 |   <div class="form-group network">
3 |     <label>Network</label>
4 |     <input type="text" class="form-control" placeholder="Enter network address" data-toggle="tooltip" title="Network address with subnet to route" autofocus>
5 |   </div>
6 | </div>
7 | 


--------------------------------------------------------------------------------
/www/templates/modalAddLocTransit.html:
--------------------------------------------------------------------------------
1 | <div class="form-group">
2 |   <label>Are you sure you want to transit the <b><%- name %></b> peer?</label>
3 | </div>
4 | 


--------------------------------------------------------------------------------
/www/templates/modalAddLocation.html:
--------------------------------------------------------------------------------
 1 | <div class="form-group">
 2 |   <div class="form-group name">
 3 |     <label>Name</label>
 4 |     <input type="text" class="form-control" placeholder="Enter name" data-toggle="tooltip" title="Name of location" autofocus>
 5 |   </div>
 6 |   <div class="form-group link">
 7 |     <label>Link</label>
 8 |     <select class="form-control">
 9 |       <% _.each(links, function(link) { %>
10 |         <% if (link.type !== 'direct') { %>
11 |           <option value="<%- link.id %>" <%= (lastLink === link.id) ? 'selected' : '' %>><%- link.name %></option>
12 |         <% } %>
13 |       <% }); %>
14 |     </select>
15 |   </div>
16 | </div>
17 | 


--------------------------------------------------------------------------------
/www/templates/modalAddOrg.html:
--------------------------------------------------------------------------------
1 | <div class="form-group">
2 |   <div class="form-group name">
3 |     <label>Name</label>
4 |     <input type="text" class="form-control" placeholder="Enter name" data-toggle="tooltip" title="Name of organization" autofocus>
5 |   </div>
6 | </div>
7 | 


--------------------------------------------------------------------------------
/www/templates/modalAddUserBulk.html:
--------------------------------------------------------------------------------
 1 | <div class="form-group users">
 2 |   <label>Enter list of usernames and optionally an email addresses on each line with a comma separating the username from the email address</label><br>
 3 |   <textarea class="form-control" rows="12" placeholder="user1,user1@pritunl.com" spellcheck="false" autofocus></textarea>
 4 | </div>
 5 | <div class="form-group org">
 6 |   <label>Select an organization</label>
 7 |   <select class="form-control">
 8 |     <% _.each(orgs, function(org) { %>
 9 |       <option value="<%- org.id %>" <%= (lastOrg === org.id) ? 'selected' : '' %>><%- org.name %></option>
10 |     <% }); %>
11 |   </select>
12 | </div>
13 | 


--------------------------------------------------------------------------------
/www/templates/modalAttachHost.html:
--------------------------------------------------------------------------------
 1 | <div class="host form-group">
 2 |   <label>Select a host</label>
 3 |   <select class="form-control">
 4 |     <% _.each(hosts, function(host) { %>
 5 |       <option value="<%- host.id %>"><%- host.name %></option>
 6 |     <% }); %>
 7 |   </select>
 8 | </div>
 9 | <div class="server form-group">
10 |   <label>Select a server</label>
11 |   <select class="form-control">
12 |     <% _.each(servers, function(server) { %>
13 |       <option value="<%- server.id %>" <%= (lastServer === server.id) ? 'selected' : '' %>><%- server.name %></option>
14 |     <% }); %>
15 |   </select>
16 | </div>
17 | 


--------------------------------------------------------------------------------
/www/templates/modalAttachLink.html:
--------------------------------------------------------------------------------
 1 | <div class="server form-group">
 2 |   <label>Select first server</label>
 3 |   <select class="form-control">
 4 |     <% _.each(servers, function(server) { %>
 5 |       <option value="<%- server.id %>" <%= server.id === servers[1].id ? 'style="display: none;"' : '' %> <%= (lastServer === server.id) ? 'selected' : '' %>><%- server.name %></option>
 6 |     <% }); %>
 7 |   </select>
 8 | </div>
 9 | <div class="link form-group">
10 |   <label>Select second server</label>
11 |   <select class="form-control">
12 |     <% _.each(servers, function(server) { %>
13 |       <option value="<%- server.id %>" <%= server.id === servers[0].id ? 'style="display: none;"' : '' %> <%= (server.id === servers[1].id) ? 'selected' : '' %>><%- server.name %></option>
14 |     <% }); %>
15 |   </select>
16 | </div>
17 | <div class="use-local-toggle toggle-form form-group">
18 |   <label>Use local address</label>
19 |   <div class="selector no-select" data-toggle="tooltip" title="Use the hosts local address when linking servers">
20 |     <span class="selector-inner glyphicon glyphicon-ok"></span>
21 |   </div>
22 | </div>
23 | 


--------------------------------------------------------------------------------
/www/templates/modalAttachOrg.html:
--------------------------------------------------------------------------------
 1 | <div class="org form-group">
 2 |   <label>Select an organization</label>
 3 |   <select class="form-control">
 4 |     <% _.each(orgs, function(org) { %>
 5 |       <option value="<%- org.id %>"><%- org.name %></option>
 6 |     <% }); %>
 7 |   </select>
 8 | </div>
 9 | <div class="server form-group">
10 |   <label>Select a server</label>
11 |   <select class="form-control">
12 |     <% _.each(servers, function(server) { %>
13 |       <option value="<%- server.id %>" <%= (lastServer === server.id) ? 'selected' : '' %>><%- server.name %></option>
14 |     <% }); %>
15 |   </select>
16 | </div>
17 | 


--------------------------------------------------------------------------------
/www/templates/modalAuditUser.html:
--------------------------------------------------------------------------------
 1 | <label class="user-title" style="<%= user.name ? '' : 'display: none' %>"><%- user.name %><%- user.email ? ' (' + user.email + ')' : '' %></label>
 2 | <ul class="modal-audit-user" style="<%= events.length ? '' : 'display: none' %>">
 3 |   <% _.each(events, function(event) { %>
 4 |   <li class="audit-event layout-horizontal">
 5 |     <span class="event-msg layout-flex">
 6 |       <span class="glyphicon glyphicon-record"></span>
 7 |       <%- event.message %>
 8 |     </span>
 9 |     <span class="event-addr" style="<%= event.remote_addr ? '' : 'display: none' %>">
10 |       <span class="glyphicon glyphicon-globe"></span>
11 |       <%- event.remote_addr %>
12 |     </span>
13 |     <span class="event-time">
14 |       <span class="glyphicon glyphicon-time"></span>
15 |       <%- window.formatTime(event.timestamp) %>
16 |     </span>
17 |   </li>
18 |   <% }); %>
19 | </ul>
20 | 


--------------------------------------------------------------------------------
/www/templates/modalDeleteAdmins.html:
--------------------------------------------------------------------------------
 1 | <div class="form-group">
 2 |   <label>Are you sure you want to logout and delete the following administrators?</label>
 3 |   <ul class="modal-user-list">
 4 |     <% _.each(admins, function(admin) { %>
 5 |       <li>
 6 |         <%- admin.username %>
 7 |       </li>
 8 |     <% }); %>
 9 |   </ul>
10 | </div>
11 | 


--------------------------------------------------------------------------------
/www/templates/modalDeleteHost.html:
--------------------------------------------------------------------------------
1 | <div class="form-group">
2 |   <label>Enter the name of the host to confirm</label>
3 |   <input type="text" class="form-control" placeholder="Enter name" data-toggle="tooltip" title="Name of host" autofocus>
4 | </div>
5 | 


--------------------------------------------------------------------------------
/www/templates/modalDeleteLink.html:
--------------------------------------------------------------------------------
1 | <div class="form-group">
2 |   <label>Enter the name of the link to confirm</label>
3 |   <input type="text" class="form-control" placeholder="Enter name" data-toggle="tooltip" title="Name of link" autofocus>
4 | </div>
5 | 


--------------------------------------------------------------------------------
/www/templates/modalDeleteLocHost.html:
--------------------------------------------------------------------------------
1 | <div class="form-group">
2 |   <label>Are you sure you want to remove the <b><%- name %></b> host?</label>
3 | </div>
4 | 


--------------------------------------------------------------------------------
/www/templates/modalDeleteLocPeer.html:
--------------------------------------------------------------------------------
1 | <div class="form-group">
2 |   <label>Are you sure you want to remove the <b><%- name %></b> peer?</label>
3 | </div>
4 | 


--------------------------------------------------------------------------------
/www/templates/modalDeleteLocRoute.html:
--------------------------------------------------------------------------------
1 | <div class="form-group">
2 |   <label>Are you sure you want to remove the <b><%- network %></b> route?</label>
3 | </div>
4 | 


--------------------------------------------------------------------------------
/www/templates/modalDeleteLocTransit.html:
--------------------------------------------------------------------------------
1 | <div class="form-group">
2 |   <label>Are you sure you want to untransit the <b><%- name %></b> peer?</label>
3 | </div>
4 | 


--------------------------------------------------------------------------------
/www/templates/modalDeleteLocation.html:
--------------------------------------------------------------------------------
1 | <div class="form-group">
2 |   <label>Enter the name of the location to confirm</label>
3 |   <input type="text" class="form-control" placeholder="Enter name" data-toggle="tooltip" title="Name of location" autofocus>
4 | </div>
5 | 


--------------------------------------------------------------------------------
/www/templates/modalDeleteOrg.html:
--------------------------------------------------------------------------------
1 | <div class="form-group">
2 |   <label>Enter the name of the organization to confirm</label>
3 |   <input type="text" class="form-control" placeholder="Enter name" data-toggle="tooltip" title="Name of organization" autofocus>
4 | </div>
5 | 


--------------------------------------------------------------------------------
/www/templates/modalDeleteServer.html:
--------------------------------------------------------------------------------
1 | <div class="form-group">
2 |   <label>Enter the name of the server to confirm</label>
3 |   <input type="text" class="form-control" placeholder="Enter name" data-toggle="tooltip" title="Name of server" autofocus>
4 | </div>
5 | 


--------------------------------------------------------------------------------
/www/templates/modalDeleteUserDevice.html:
--------------------------------------------------------------------------------
1 | <div class="form-group">
2 |   <label>Are you sure you want to remove the <b><%- name %></b> device?</label>
3 | </div>
4 | 


--------------------------------------------------------------------------------
/www/templates/modalDeleteUsers.html:
--------------------------------------------------------------------------------
 1 | <div class="form-group">
 2 |   <label>Are you sure you want to disconnect and delete the following users?</label>
 3 |   <ul class="modal-user-list">
 4 |     <% _.each(users, function(user) { %>
 5 |       <li>
 6 |         <%- user.name %>
 7 |       </li>
 8 |     <% }); %>
 9 |   </ul>
10 | </div>
11 | 


--------------------------------------------------------------------------------
/www/templates/modalDetachHost.html:
--------------------------------------------------------------------------------
1 | <div class="form-group">
2 |   <label>Are you sure you want to detach the <b><%- name %></b> host?</label>
3 | </div>
4 | 


--------------------------------------------------------------------------------
/www/templates/modalDetachLink.html:
--------------------------------------------------------------------------------
1 | <div class="form-group">
2 |   <label>Are you sure you want to detach the <b><%- name %></b> link?</label>
3 | </div>
4 | 


--------------------------------------------------------------------------------
/www/templates/modalDetachOrg.html:
--------------------------------------------------------------------------------
1 | <div class="form-group">
2 |   <label>Are you sure you want to detach the <b><%- name %></b> organization?</label>
3 | </div>
4 | 


--------------------------------------------------------------------------------
/www/templates/modalDeviceRegister.html:
--------------------------------------------------------------------------------
1 | <div class="form-group">
2 |   <div class="form-group reg-key">
3 |     <label>Registration Key</label>
4 |     <input type="text" class="form-control" placeholder="Enter registration key" data-toggle="tooltip" title="Device registration key, provided by user" autofocus>
5 |   </div>
6 | </div>
7 | 


--------------------------------------------------------------------------------
/www/templates/modalEmailUsers.html:
--------------------------------------------------------------------------------
 1 | <div class="form-group">
 2 |   <label>Are you sure you want to email a key link to the following users?</label>
 3 |   <ul class="modal-user-list">
 4 |     <% _.each(users, function(user) { %>
 5 |       <li class="user-<%- user.id %>">
 6 |         <%- user.name %><%- user.email ? ' (' + user.email + ')' : '' %>
 7 |       </li>
 8 |     <% }); %>
 9 |   </ul>
10 | </div>
11 | 


--------------------------------------------------------------------------------
/www/templates/modalLocHostConf.html:
--------------------------------------------------------------------------------
1 | <div class="conf-link form-group">
2 |   <label>Host Static Configuration</label>
3 |   <textarea class="form-control" rows="16" spellcheck="false" readonly></textarea>
4 | </div>
5 | 


--------------------------------------------------------------------------------
/www/templates/modalLocHostUri.html:
--------------------------------------------------------------------------------
1 | <div class="uri-link form-group">
2 |   <label>Host URI Link</label>
3 |   <input type="text" class="form-control" readonly>
4 | </div>
5 | 


--------------------------------------------------------------------------------
/www/templates/modalModifyLocation.html:
--------------------------------------------------------------------------------
1 | <div class="form-group">
2 |   <div class="form-group name">
3 |     <label>Name</label>
4 |     <input type="text" class="form-control" placeholder="Enter name" data-toggle="tooltip" title="Name of location" autofocus value="<%- name %>">
5 |   </div>
6 | </div>
7 | 


--------------------------------------------------------------------------------
/www/templates/modalNotification.html:
--------------------------------------------------------------------------------
1 | <div class="notification">
2 |   <%- notification %>
3 | </div>
4 | 


--------------------------------------------------------------------------------
/www/templates/modalOtpAuth.html:
--------------------------------------------------------------------------------
1 | <div class="otp-auth-key form-group">
2 |   <label>Two-step authentication key</label>
3 |   <input type="text" class="form-control" readonly>
4 |   <div class="qrcode"></div>
5 |   <button type="button" class="generate-new-key btn btn-danger">Generate New Key</button>
6 | </div>
7 | 


--------------------------------------------------------------------------------
/www/templates/modalRekeyLink.html:
--------------------------------------------------------------------------------
1 | <div class="form-group">
2 |   <label>Are you sure you want to regenerate the secret key for <b><%- name %></b> link?</label>
3 | </div>
4 | 


--------------------------------------------------------------------------------
/www/templates/modalRemoveRoute.html:
--------------------------------------------------------------------------------
1 | <div class="form-group">
2 |   <label>Are you sure you want to remove the <b><%- network %></b> route?</label>
3 | </div>
4 | 


--------------------------------------------------------------------------------
/www/templates/modalRenameOrg.html:
--------------------------------------------------------------------------------
1 | <div class="form-group">
2 |   <div class="form-group name">
3 |     <label>Name</label>
4 |     <input type="text" class="form-control" placeholder="Enter name" data-toggle="tooltip" title="Name of organization" value="<%- name %>" autofocus>
5 |   </div>
6 | </div>
7 | 


--------------------------------------------------------------------------------
/www/templates/orgsListItem.html:
--------------------------------------------------------------------------------
 1 | <div class="users-list-header">
 2 |   <div class="label label-success toggle-hidden no-select">Organization</div><h2 class="users-list-title title"><a class="org-title no-select" data-toggle="tooltip" title="Click to modify this organization"><%- name %></a><span class="org-id title"> (<%- id %>)</span></h2>
 3 |   <button type="button" class="org-del btn btn-danger btn-sm">Delete Organization</button>
 4 |   <button type="button" class="org-sort btn btn-primary btn-sm">Sort by <%- sort_active ? 'Name' : 'Last Active' %></button>
 5 |   <input type="text" class="org-search form-control" placeholder="Search for user" autocomplete="off">
 6 |   <div class="user-count label label-default no-select">
 7 |     <%- user_count %> users
 8 |   </div>
 9 | </div>
10 | 


--------------------------------------------------------------------------------
/www/templates/serverBandwidth.html:
--------------------------------------------------------------------------------
1 | <div class="server-graph-recv"></div>
2 | <div class="server-graph-sent"></div>
3 | 


--------------------------------------------------------------------------------
/www/templates/serverHostsList.html:
--------------------------------------------------------------------------------
1 | <div class="no-hosts">
2 |   There are no hosts attached to this server.
3 | </div>
4 | 


--------------------------------------------------------------------------------
/www/templates/serverHostsListItem.html:
--------------------------------------------------------------------------------
 1 | <div class="name-container">
 2 |   <span class="name-icon glyphicon glyphicon-dashboard"></span>
 3 |   <span class="host-name title"><%- name %></span>
 4 |   <span class="host-public-address title"><%- address ? '(' + address + ')' : ''%></span>
 5 |   <span class="host-id title">(<%- id %>)</span>
 6 | </div>
 7 | <div class="button-container">
 8 |   <div class="host-online label label-success no-select" <%= status === 'online' ? '' : 'style="display: none;"' %>>Online</div>
 9 |   <div class="host-offline label label-danger no-select" <%= status === 'offline' ? '' : 'style="display: none;"' %>>Offline</div>
10 |   <button type="button" class="server-detach-host btn btn-danger btn-xs">Detach Host</button>
11 | </div>
12 | 


--------------------------------------------------------------------------------
/www/templates/serverLinksList.html:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/templates/serverLinksList.html


--------------------------------------------------------------------------------
/www/templates/serverLinksListItem.html:
--------------------------------------------------------------------------------
 1 | <div class="name-container">
 2 |   <span class="name-icon glyphicon glyphicon-transfer"></span>
 3 |   <span class="link-name title"><%- name %></span>
 4 |   <span class="link-id title">(<%- id %>)</span>
 5 | </div>
 6 | <div class="button-container">
 7 |   <div class="link-use-local label label-default no-select" <%= use_local_address ? '' : 'style="display: none;"' %>>LAN</div>
 8 |   <div class="link-online label label-success no-select" <%= status === 'online' ? '' : 'style="display: none;"' %>>Online</div>
 9 |   <div class="link-offline label label-danger no-select" <%= status === 'offline' ? '' : 'style="display: none;"' %>>Offline</div>
10 |   <button type="button" class="server-detach-link btn btn-danger btn-xs">Unlink Server</button>
11 | </div>
12 | 


--------------------------------------------------------------------------------
/www/templates/serverOrgsList.html:
--------------------------------------------------------------------------------
1 | <div class="no-orgs">
2 |   There are no organizations attached to this server.
3 | </div>
4 | 


--------------------------------------------------------------------------------
/www/templates/serverOrgsListItem.html:
--------------------------------------------------------------------------------
1 | <div class="name-container">
2 |   <span class="name-icon glyphicon glyphicon-tower"></span>
3 |   <span class="org-name title"><%- name %></span>
4 |   <span class="org-id title">(<%- id %>)</span>
5 | </div>
6 | <div class="button-container">
7 |   <button type="button" class="server-detach-org btn btn-danger btn-xs">Detach Organization</button>
8 | </div>
9 | 


--------------------------------------------------------------------------------
/www/templates/serverRoutesList.html:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/templates/serverRoutesList.html


--------------------------------------------------------------------------------
/www/templates/userDevicesList.html:
--------------------------------------------------------------------------------
1 | <div class="user-devices">
2 |   <div class="no-devices title">
3 |     No devices available
4 |   </div>
5 | </div>
6 | 


--------------------------------------------------------------------------------
/www/templates/userDevicesListItem.html:
--------------------------------------------------------------------------------
 1 | <div class="layout-horizontal">
 2 |   <div class="info-container layout-flex">
 3 |     <div class="server-name-device">
 4 |       <div class="user-device-label user-device-unregisted-label label label-danger toggle-hidden no-select">Unregistered</div>
 5 |       <span class="server-item device-name" data-toggle="tooltip" title="Device name">
 6 |         <span class="name-icon glyphicon glyphicon-tasks"></span>
 7 |         <span class="title"></span>
 8 |       </span>
 9 |     </div>
10 |   </div>
11 |   <div class="client-container">
12 |     <span class="server-item device-time" data-toggle="tooltip" title="Last connected">
13 |       <span class="name-icon glyphicon glyphicon-time"></span>
14 |       <span class="title"></span>
15 |     </span>
16 |   </div>
17 |   <div class="button-container">
18 |     <button type="button" class="user-device-reg btn btn-primary btn-xs">Register Device</button>
19 |     <button type="button" class="user-device-del btn btn-danger btn-xs">Remove Device</button>
20 |   </div>
21 | </div>
22 | 


--------------------------------------------------------------------------------
/www/templates/userServersList.html:
--------------------------------------------------------------------------------
1 | <div class="no-servers title">
2 |   No servers available
3 | </div>
4 | 


--------------------------------------------------------------------------------
/www/templates/usersList.html:
--------------------------------------------------------------------------------
 1 | <div class="no-users">
 2 |   There are no users in this organization
 3 | </div>
 4 | <div class="no-users-search">
 5 |   No users found
 6 | </div>
 7 | <div class="loading">
 8 |   Loading...
 9 | </div>
10 | <button type="button" class="prev-page btn btn-primary btn-sm">Previous Page</button>
11 | <button type="button" class="next-page btn btn-primary btn-sm">Next Page</button>
12 | <div class="pages no-select">
13 |   <div class="links">
14 |     <a class="link first">First</a>
15 |     <a class="link last">Last</a>
16 |   </div>
17 | </div>
18 | <div class="search-time no-select"></div>
19 | <div class="search-more">
20 |   <a class="no-select">show more results</a>
21 | </div>
22 | 


--------------------------------------------------------------------------------
/www/vendor/ace/mode-text.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/vendor/ace/mode-text.js


--------------------------------------------------------------------------------
/www/vendor/dist/fonts/FontAwesome.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/vendor/dist/fonts/FontAwesome.otf


--------------------------------------------------------------------------------
/www/vendor/dist/fonts/fontawesome-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/vendor/dist/fonts/fontawesome-webfont.eot


--------------------------------------------------------------------------------
/www/vendor/dist/fonts/fontawesome-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/vendor/dist/fonts/fontawesome-webfont.ttf


--------------------------------------------------------------------------------
/www/vendor/dist/fonts/fontawesome-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/vendor/dist/fonts/fontawesome-webfont.woff


--------------------------------------------------------------------------------
/www/vendor/dist/fonts/fontawesome-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/vendor/dist/fonts/fontawesome-webfont.woff2


--------------------------------------------------------------------------------
/www/vendor/dist/fonts/fredoka-one.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/vendor/dist/fonts/fredoka-one.eot


--------------------------------------------------------------------------------
/www/vendor/dist/fonts/fredoka-one.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/vendor/dist/fonts/fredoka-one.woff


--------------------------------------------------------------------------------
/www/vendor/dist/fonts/glyphicons-halflings-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/vendor/dist/fonts/glyphicons-halflings-regular.eot


--------------------------------------------------------------------------------
/www/vendor/dist/fonts/glyphicons-halflings-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/vendor/dist/fonts/glyphicons-halflings-regular.ttf


--------------------------------------------------------------------------------
/www/vendor/dist/fonts/glyphicons-halflings-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/vendor/dist/fonts/glyphicons-halflings-regular.woff


--------------------------------------------------------------------------------
/www/vendor/dist/fonts/ubuntu-bold.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/vendor/dist/fonts/ubuntu-bold.eot


--------------------------------------------------------------------------------
/www/vendor/dist/fonts/ubuntu-bold.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/vendor/dist/fonts/ubuntu-bold.woff


--------------------------------------------------------------------------------
/www/vendor/dist/fonts/ubuntu.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/vendor/dist/fonts/ubuntu.eot


--------------------------------------------------------------------------------
/www/vendor/dist/fonts/ubuntu.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pritunl/pritunl/ab6498e5ddee639f010c279f565b354d12a3e745/www/vendor/dist/fonts/ubuntu.woff


--------------------------------------------------------------------------------
/www/vendor/dist/robots.txt:
--------------------------------------------------------------------------------
1 | User-agent: *
2 | Disallow: /
3 | 


--------------------------------------------------------------------------------
/www/views/dashboard.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone',
 5 |   'views/dashboardStatus',
 6 |   'views/devicesList',
 7 |   'views/dashboardLog',
 8 |   'text!templates/dashboard.html'
 9 | ], function($, _, Backbone, DashboardStatusView, DevicesListView,
10 |     DashboardLogView, dashboardTemplate) {
11 |   'use strict';
12 |   var DashboardView = Backbone.View.extend({
13 |     className: 'dashboard container',
14 |     template: _.template(dashboardTemplate),
15 |     initialize: function() {
16 |       this.dashboardStatusView = new DashboardStatusView();
17 |       this.addView(this.dashboardStatusView);
18 |       this.devicesListView = new DevicesListView();
19 |       this.addView(this.devicesListView);
20 |       this.dashboardLogView = new DashboardLogView();
21 |       this.addView(this.dashboardLogView);
22 |     },
23 |     render: function() {
24 |       this.$el.html(this.template());
25 |       this.$el.prepend(this.dashboardStatusView.render().el);
26 |       this.$el.append(this.devicesListView.render().el);
27 |       this.$el.append(this.dashboardLogView.render().el);
28 |       return this;
29 |     }
30 |   });
31 | 
32 |   return DashboardView;
33 | });
34 | 


--------------------------------------------------------------------------------
/www/views/dashboardLogItem.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone',
 5 |   'text!templates/dashboardLogItem.html'
 6 | ], function($, _, Backbone, dashboardLogItemTemplate) {
 7 |   'use strict';
 8 |   var DashboardLogItemView = Backbone.View.extend({
 9 |     className: 'log-entry clearfix',
10 |     template: _.template(dashboardLogItemTemplate),
11 |     render: function() {
12 |       this.$el.html(this.template(this.model.toJSON()));
13 |       return this;
14 |     },
15 |     update: function() {
16 |       this.$('.log-msg').text(this.model.get('message'));
17 |       this.$('.log-time').text(window.formatTime(this.model.get('timestamp')));
18 |     }
19 |   });
20 | 
21 |   return DashboardLogItemView;
22 | });
23 | 


--------------------------------------------------------------------------------
/www/views/devices.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone',
 5 |   'views/devicesList'
 6 | ], function($, _, Backbone, DevicesListView) {
 7 |   'use strict';
 8 |   var DevicesView = Backbone.View.extend({
 9 |     className: 'devices container',
10 |     initialize: function() {
11 |       this.devicesList = new DevicesListView();
12 |       this.addView(this.devicesList);
13 |     },
14 |     render: function() {
15 |       this.$el.append(this.devicesList.render().el);
16 |       return this;
17 |     }
18 |   });
19 | 
20 |   return DevicesView;
21 | });
22 | 


--------------------------------------------------------------------------------
/www/views/hosts.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone',
 5 |   'views/hostsList'
 6 | ], function($, _, Backbone, HostsListView) {
 7 |   'use strict';
 8 |   var HostsView = Backbone.View.extend({
 9 |     className: 'hosts container',
10 |     initialize: function() {
11 |       this.hostsList = new HostsListView();
12 |       this.addView(this.hostsList);
13 |     },
14 |     render: function() {
15 |       this.$el.append(this.hostsList.render().el);
16 |       return this;
17 |     }
18 |   });
19 | 
20 |   return HostsView;
21 | });
22 | 


--------------------------------------------------------------------------------
/www/views/links.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone',
 5 |   'views/linksList'
 6 | ], function($, _, Backbone, LinksListView) {
 7 |   'use strict';
 8 |   var LinksView = Backbone.View.extend({
 9 |     className: 'links container',
10 |     initialize: function() {
11 |       this.linksList = new LinksListView();
12 |       this.addView(this.linksList);
13 |     },
14 |     render: function() {
15 |       this.$el.append(this.linksList.render().el);
16 |       return this;
17 |     }
18 |   });
19 | 
20 |   return LinksView;
21 | });
22 | 


--------------------------------------------------------------------------------
/www/views/loginBackdrop.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone'
 5 | ], function($, _, Backbone) {
 6 |   'use strict';
 7 |   var LoginBackdropView = Backbone.View.extend({
 8 |     className: 'login-backdrop'
 9 |   });
10 | 
11 |   return LoginBackdropView;
12 | });
13 | 


--------------------------------------------------------------------------------
/www/views/modalDetachHost.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone',
 5 |   'views/modal',
 6 |   'views/alert',
 7 |   'text!templates/modalDetachHost.html'
 8 | ], function($, _, Backbone, ModalView, AlertView, modalDetachHostTemplate) {
 9 |   'use strict';
10 |   var ModalDetachHostView = ModalView.extend({
11 |     className: 'detach-host-modal',
12 |     template: _.template(modalDetachHostTemplate),
13 |     title: 'Detach Host',
14 |     okText: 'Detach',
15 |     body: function() {
16 |       return this.template(this.model.toJSON());
17 |     },
18 |     onOk: function() {
19 |       this.setLoading('Detaching host...');
20 |       this.model.destroy({
21 |         success: function() {
22 |           this.close(true);
23 |         }.bind(this),
24 |         error: function(model, response) {
25 |           this.clearLoading();
26 |           if (response.responseJSON) {
27 |             this.setAlert('danger', response.responseJSON.error_msg);
28 |           }
29 |           else {
30 |             this.setAlert('danger', this.errorMsg);
31 |           }
32 |         }.bind(this)
33 |       });
34 |     }
35 |   });
36 | 
37 |   return ModalDetachHostView;
38 | });
39 | 


--------------------------------------------------------------------------------
/www/views/modalLogs.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone',
 5 |   'views/modal',
 6 |   'views/alert',
 7 |   'views/logs'
 8 | ], function($, _, Backbone, ModalView, AlertView, LogsView) {
 9 |   'use strict';
10 |   var ModalLogsView = ModalView.extend({
11 |     className: 'logs-modal',
12 |     title: 'System Logs',
13 |     okText: 'Close',
14 |     cancelText: null,
15 |     initialize: function() {
16 |       this.logsView = new LogsView();
17 |       this.addView(this.logsView);
18 |       ModalLogsView.__super__.initialize.call(this);
19 |     },
20 |     postRender: function() {
21 |       this.$('.modal-body').append(
22 |         this.logsView.render().el);
23 |     }
24 |   });
25 | 
26 |   return ModalLogsView;
27 | });
28 | 


--------------------------------------------------------------------------------
/www/views/modalNotification.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone',
 5 |   'models/org',
 6 |   'views/modal',
 7 |   'text!templates/modalNotification.html'
 8 | ], function($, _, Backbone, OrgModel, ModalView, modalNotificationTemplate) {
 9 |   'use strict';
10 |   var ModalNotificationView = ModalView.extend({
11 |     className: 'notification-modal',
12 |     template: _.template(modalNotificationTemplate),
13 |     title: 'Update Notification',
14 |     okText: 'Close',
15 |     cancelText: null,
16 |     body: function() {
17 |       return this.template(this.model.toJSON());
18 |     }
19 |   });
20 | 
21 |   return ModalNotificationView;
22 | });
23 | 


--------------------------------------------------------------------------------
/www/views/modalRekeyLink.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone',
 5 |   'views/modal',
 6 |   'views/alert',
 7 |   'text!templates/modalRekeyLink.html'
 8 | ], function($, _, Backbone, ModalView, AlertView, modalRekeyLinkTemplate) {
 9 |   'use strict';
10 |   var ModalRekeyLinkView = ModalView.extend({
11 |     className: 'rekey-link-modal',
12 |     template: _.template(modalRekeyLinkTemplate),
13 |     title: 'Rekey Link',
14 |     okText: 'Rekey',
15 |     body: function() {
16 |       return this.template(this.model.toJSON());
17 |     },
18 |     onOk: function() {
19 |       this.setLoading('Rekeying link...');
20 |       this.model.save({
21 |         key: true
22 |       }, {
23 |         success: function() {
24 |           this.close(true);
25 |         }.bind(this),
26 |         error: function(model, response) {
27 |           this.clearLoading();
28 |           if (response.responseJSON) {
29 |             this.setAlert('danger', response.responseJSON.error_msg);
30 |           }
31 |           else {
32 |             this.setAlert('danger', this.errorMsg);
33 |           }
34 |         }.bind(this)
35 |       });
36 |     }
37 |   });
38 | 
39 |   return ModalRekeyLinkView;
40 | });
41 | 


--------------------------------------------------------------------------------
/www/views/modalRemoveRoute.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone',
 5 |   'views/modal',
 6 |   'views/alert',
 7 |   'text!templates/modalRemoveRoute.html'
 8 | ], function($, _, Backbone, ModalView, AlertView, modalRemoveRouteTemplate) {
 9 |   'use strict';
10 |   var ModalRemoveRouteView = ModalView.extend({
11 |     className: 'remove-route-modal',
12 |     template: _.template(modalRemoveRouteTemplate),
13 |     title: 'Remove Route',
14 |     okText: 'Remove',
15 |     body: function() {
16 |       return this.template(this.model.toJSON());
17 |     },
18 |     onOk: function() {
19 |       this.setLoading('Removing route...');
20 |       this.model.destroy({
21 |         success: function() {
22 |           this.close(true);
23 |         }.bind(this),
24 |         error: function(model, response) {
25 |           this.clearLoading();
26 |           if (response.responseJSON) {
27 |             this.setAlert('danger', response.responseJSON.error_msg);
28 |           }
29 |           else {
30 |             this.setAlert('danger', this.errorMsg);
31 |           }
32 |         }.bind(this)
33 |       });
34 |     }
35 |   });
36 | 
37 |   return ModalRemoveRouteView;
38 | });
39 | 


--------------------------------------------------------------------------------
/www/views/serverOutputLink.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone',
 5 |   'models/serverOutputLink',
 6 |   'views/serverOutput'
 7 | ], function($, _, Backbone, ServerOutputLinkModel, ServerOutputView) {
 8 |   'use strict';
 9 |   var ServerOutputLinkView = ServerOutputView.extend({
10 |     errorMsg: 'Failed to load server link output, server error occurred.',
11 |     initialize: function(options) {
12 |       this.model = new ServerOutputLinkModel({
13 |         id: options.server
14 |       });
15 |       this.state = false;
16 |       this.listenTo(window.events, 'server_link_output_updated:' +
17 |           options.server, this.update);
18 |     }
19 |   });
20 | 
21 |   return ServerOutputLinkView;
22 | });
23 | 


--------------------------------------------------------------------------------
/www/views/servers.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone',
 5 |   'views/serversList'
 6 | ], function($, _, Backbone, ServersListView) {
 7 |   'use strict';
 8 |   var ServersView = Backbone.View.extend({
 9 |     className: 'servers container',
10 |     initialize: function() {
11 |       this.serversList = new ServersListView();
12 |       this.addView(this.serversList);
13 |     },
14 |     render: function() {
15 |       this.$el.append(this.serversList.render().el);
16 |       return this;
17 |     }
18 |   });
19 | 
20 |   return ServersView;
21 | });
22 | 


--------------------------------------------------------------------------------
/www/views/users.js:
--------------------------------------------------------------------------------
 1 | define([
 2 |   'jquery',
 3 |   'underscore',
 4 |   'backbone',
 5 |   'views/orgsList'
 6 | ], function($, _, Backbone, OrgsListView) {
 7 |   'use strict';
 8 |   var UsersView = Backbone.View.extend({
 9 |     className: 'users container',
10 |     initialize: function() {
11 |       this.orgsList = new OrgsListView();
12 |       this.addView(this.orgsList);
13 |     },
14 |     render: function() {
15 |       this.$el.append(this.orgsList.render().el);
16 |       return this;
17 |     }
18 |   });
19 | 
20 |   return UsersView;
21 | });
22 | 


--------------------------------------------------------------------------------