forked from trashmodern/vaultwarden
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ebb30229f1 | |||
| 936af5431a |
@@ -1,55 +1,13 @@
|
||||
## Bitwarden_RS Configuration File
|
||||
## Uncomment any of the following lines to change the defaults
|
||||
|
||||
## Main data folder
|
||||
# DATA_FOLDER=data
|
||||
|
||||
## Individual folders, these override %DATA_FOLDER%
|
||||
# DATABASE_URL=data/db.sqlite3
|
||||
# RSA_KEY_FILENAME=data/rsa_key
|
||||
# PRIVATE_RSA_KEY=data/private_rsa_key.der
|
||||
# PUBLIC_RSA_KEY=data/public_rsa_key.der
|
||||
# ICON_CACHE_FOLDER=data/icon_cache
|
||||
# ATTACHMENTS_FOLDER=data/attachments
|
||||
|
||||
## Web vault settings
|
||||
# WEB_VAULT_FOLDER=web-vault/
|
||||
# WEB_VAULT_ENABLED=true
|
||||
# true for yes, anything else for no
|
||||
SIGNUPS_ALLOWED=true
|
||||
|
||||
## Controls the WebSocket server port
|
||||
# WEBSOCKET_PORT=3012
|
||||
|
||||
## Controls if new users can register
|
||||
# SIGNUPS_ALLOWED=true
|
||||
|
||||
## Use a local favicon extractor
|
||||
## Set to false to use bitwarden's official icon servers
|
||||
## Set to true to use the local version, which is not as smart,
|
||||
## but it doesn't send the cipher domains to bitwarden's servers
|
||||
# LOCAL_ICON_EXTRACTOR=false
|
||||
|
||||
## Controls the PBBKDF password iterations to apply on the server
|
||||
## The change only applies when the password is changed
|
||||
# PASSWORD_ITERATIONS=100000
|
||||
|
||||
## Whether password hint should be sent into the error response when the client request it
|
||||
# SHOW_PASSWORD_HINT=true
|
||||
|
||||
## Domain settings
|
||||
## The domain must match the address from where you access the server
|
||||
## Unless you are using U2F, or having problems with attachments not downloading, there is no need to change this
|
||||
## For U2F to work, the server must use HTTPS, you can use Let's Encrypt for free certs
|
||||
# DOMAIN=https://bw.domain.tld:8443
|
||||
|
||||
## Rocket specific settings, check Rocket documentation to learn more
|
||||
# ROCKET_ENV=staging
|
||||
# ROCKET_ENV=production
|
||||
# ROCKET_ADDRESS=0.0.0.0 # Enable this to test mobile app
|
||||
# ROCKET_PORT=8000
|
||||
# ROCKET_TLS={certs="/path/to/certs.pem",key="/path/to/key.pem"}
|
||||
|
||||
## Mail specific settings, set SMTP_HOST and SMTP_FROM to enable the mail service.
|
||||
## Note: if SMTP_USERNAME is specified, SMTP_PASSWORD is mandatory
|
||||
# SMTP_HOST=smtp.domain.tld
|
||||
# SMTP_FROM=bitwarden-rs@domain.tld
|
||||
# SMTP_PORT=587
|
||||
# SMTP_SSL=true
|
||||
# SMTP_USERNAME=username
|
||||
# SMTP_PASSWORD=password
|
||||
@@ -1,7 +0,0 @@
|
||||
# Copied from Rocket's .travis.yml
|
||||
language: rust
|
||||
sudo: required # so we get a VM with higher specs
|
||||
dist: trusty # so we get a VM with higher specs
|
||||
cache: cargo
|
||||
rust:
|
||||
- nightly
|
||||
@@ -1,55 +1,56 @@
|
||||
# Build instructions
|
||||
## How to compile bitwarden_rs
|
||||
Install `rust nightly`, in Windows the recommended way is through `rustup`.
|
||||
|
||||
## Dependencies
|
||||
- `Rust nightly` (strongly recommended to use [rustup](https://rustup.rs/))
|
||||
- `OpenSSL` (should be available in path, install through your system's package manager or use the [prebuilt binaries](https://wiki.openssl.org/index.php/Binaries))
|
||||
- `NodeJS` (required to build the web-vault, (install through your system's package manager or use the [prebuilt binaries](https://nodejs.org/en/download/))
|
||||
Install the `openssl` library, in Windows the best option is Microsoft's `vcpkg`,
|
||||
on other systems use their respective package managers.
|
||||
|
||||
|
||||
## Run/Compile
|
||||
Then run:
|
||||
```sh
|
||||
# Compile and run
|
||||
cargo run
|
||||
# or just compile (binary located in target/release/bitwarden_rs)
|
||||
cargo build --release
|
||||
# or
|
||||
cargo build
|
||||
```
|
||||
|
||||
When run, the server is accessible in [http://localhost:80](http://localhost:80).
|
||||
## How to install the web-vault locally
|
||||
If you're using docker image, you can just update `VAULT_VERSION` variable in Dockerfile and rebuild the image.
|
||||
|
||||
### Install the web-vault
|
||||
Clone the git repository at [bitwarden/web](https://github.com/bitwarden/web) and checkout the latest release tag (e.g. v2.1.1):
|
||||
```sh
|
||||
# clone the repository
|
||||
Install `node.js` and either `yarn` or `npm` (usually included with node)
|
||||
|
||||
Clone the web-vault outside the project:
|
||||
```
|
||||
git clone https://github.com/bitwarden/web.git web-vault
|
||||
cd web-vault
|
||||
# switch to the latest tag
|
||||
git checkout "$(git tag | tail -n1)"
|
||||
```
|
||||
|
||||
Apply the patch file from `docker/set-vault-baseurl.patch`:
|
||||
```sh
|
||||
# In the Vault repository directory
|
||||
git apply /path/to/bitwarden_rs/docker/set-vault-baseurl.patch
|
||||
Modify `web-vault/settings.Production.json` to look like this:
|
||||
```json
|
||||
{
|
||||
"appSettings": {
|
||||
"apiUri": "/api",
|
||||
"identityUri": "/identity",
|
||||
"iconsUri": "/icons",
|
||||
"stripeKey": "",
|
||||
"braintreeKey": ""
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then, build the Vault:
|
||||
Then, run the following from the `web-vault` dir:
|
||||
```sh
|
||||
npm run sub:init
|
||||
# With yarn (recommended)
|
||||
yarn
|
||||
yarn gulp dist:selfHosted
|
||||
|
||||
# With npm
|
||||
npm install
|
||||
npm run dist
|
||||
npx gulp dist:selfHosted
|
||||
```
|
||||
|
||||
Finally copy the contents of the `build` folder into the `bitwarden_rs/web-vault` folder.
|
||||
Finally copy the contents of the `web-vault/dist` folder into the `bitwarden_rs/web-vault` folder.
|
||||
|
||||
# Configuration
|
||||
The available configuration options are documented in the default `.env` file, and they can be modified by uncommenting the desired options in that file or by setting their respective environment variables. Look at the README file for the main configuration options available.
|
||||
|
||||
Note: the environment variables override the values set in the `.env` file.
|
||||
|
||||
## How to recreate database schemas (for developers)
|
||||
## How to recreate database schemas
|
||||
Install diesel-cli with cargo:
|
||||
```sh
|
||||
cargo install diesel_cli --no-default-features --features sqlite-bundled
|
||||
cargo install diesel_cli --no-default-features --features sqlite-bundled # Or use only sqlite to use the system version
|
||||
```
|
||||
|
||||
Make sure that the correct path to the database is in the `.env` file.
|
||||
@@ -62,9 +63,7 @@ diesel migration generate <name>
|
||||
Modify the *.sql files, making sure that any changes are reverted in the down.sql file.
|
||||
|
||||
Apply the migrations and save the generated schemas as follows:
|
||||
```sh
|
||||
diesel migration redo
|
||||
|
||||
# This step should be done automatically when using diesel-cli > 1.3.0
|
||||
# diesel print-schema > src/db/schema.rs
|
||||
```
|
||||
diesel migration redo
|
||||
diesel print-schema > src/db/schema.rs
|
||||
```
|
||||
Generated
+632
-1048
File diff suppressed because it is too large
Load Diff
+16
-48
@@ -1,49 +1,40 @@
|
||||
[package]
|
||||
name = "bitwarden_rs"
|
||||
version = "1.0.0"
|
||||
version = "0.9.0"
|
||||
authors = ["Daniel García <dani-garcia@users.noreply.github.com>"]
|
||||
|
||||
[dependencies]
|
||||
# Web framework for nightly with a focus on ease-of-use, expressibility, and speed.
|
||||
rocket = { version = "0.3.16", features = ["tls"] }
|
||||
rocket_codegen = "0.3.16"
|
||||
rocket_contrib = "0.3.16"
|
||||
rocket = { version = "0.3.12", features = ["tls"] }
|
||||
rocket_codegen = "0.3.12"
|
||||
rocket_contrib = "0.3.12"
|
||||
|
||||
# HTTP client
|
||||
reqwest = "0.9.0"
|
||||
reqwest = "0.8.6"
|
||||
|
||||
# multipart/form-data support
|
||||
multipart = "0.15.3"
|
||||
|
||||
# WebSockets library
|
||||
ws = "0.7.8"
|
||||
|
||||
# MessagePack library
|
||||
rmpv = "0.4.0"
|
||||
|
||||
# Concurrent hashmap implementation
|
||||
chashmap = "2.2.0"
|
||||
multipart = "0.14.2"
|
||||
|
||||
# A generic serialization/deserialization framework
|
||||
serde = "1.0.79"
|
||||
serde_derive = "1.0.79"
|
||||
serde_json = "1.0.28"
|
||||
serde = "1.0.64"
|
||||
serde_derive = "1.0.64"
|
||||
serde_json = "1.0.19"
|
||||
|
||||
# A safe, extensible ORM and Query builder
|
||||
diesel = { version = "1.3.3", features = ["sqlite", "chrono", "r2d2"] }
|
||||
diesel_migrations = { version = "1.3.0", features = ["sqlite"] }
|
||||
diesel = { version = "~1.2.2", features = ["sqlite", "chrono", "r2d2"] }
|
||||
diesel_migrations = { version = "~1.2.0", features = ["sqlite"] }
|
||||
|
||||
# Bundled SQLite
|
||||
libsqlite3-sys = { version = "0.9.3", features = ["bundled"] }
|
||||
libsqlite3-sys = { version = "0.9.1", features = ["bundled"] }
|
||||
|
||||
# Crypto library
|
||||
ring = { version = "= 0.11.0", features = ["rsa_signing"] }
|
||||
|
||||
# UUID generation
|
||||
uuid = { version = "0.7.1", features = ["v4"] }
|
||||
uuid = { version = "0.6.5", features = ["v4"] }
|
||||
|
||||
# Date and time library for Rust
|
||||
chrono = "0.4.6"
|
||||
chrono = "0.4.2"
|
||||
|
||||
# TOTP library
|
||||
oath = "0.10.2"
|
||||
@@ -54,34 +45,11 @@ data-encoding = "2.1.1"
|
||||
# JWT library
|
||||
jsonwebtoken = "= 4.0.1"
|
||||
|
||||
# U2F library
|
||||
u2f = "0.1.2"
|
||||
|
||||
# A `dotenv` implementation for Rust
|
||||
dotenv = { version = "0.13.0", default-features = false }
|
||||
|
||||
# Lazy static macro
|
||||
lazy_static = "1.1.0"
|
||||
|
||||
# Numerical libraries
|
||||
num-traits = "0.2.6"
|
||||
num-derive = "0.2.2"
|
||||
|
||||
# Email libraries
|
||||
lettre = "0.9.0"
|
||||
lettre_email = "0.9.0"
|
||||
native-tls = "0.2.1"
|
||||
fast_chemail = "0.9.5"
|
||||
|
||||
# Number encoding library
|
||||
byteorder = "1.2.6"
|
||||
lazy_static = "1.0.1"
|
||||
|
||||
[patch.crates-io]
|
||||
# Make jwt use ring 0.11, to match rocket
|
||||
jsonwebtoken = { path = "libs/jsonwebtoken" }
|
||||
rmp = { git = 'https://github.com/dani-garcia/msgpack-rust' }
|
||||
lettre = { git = 'https://github.com/lettre/lettre', rev = 'fc91bb6ee8f9a' }
|
||||
lettre_email = { git = 'https://github.com/lettre/lettre', rev = 'fc91bb6ee8f9a' }
|
||||
|
||||
# Version 0.1.2 from crates.io lacks a commit that fixes a certificate error
|
||||
u2f = { git = 'https://github.com/wisespace-io/u2f-rs', rev = '193de35093a44' }
|
||||
jsonwebtoken = { path = "libs/jsonwebtoken" } # Make jwt use ring 0.11, to match rocket
|
||||
|
||||
+20
-21
@@ -2,32 +2,36 @@
|
||||
# https://docs.docker.com/develop/develop-images/multistage-build/
|
||||
# https://whitfin.io/speeding-up-rust-docker-builds/
|
||||
####################### VAULT BUILD IMAGE #######################
|
||||
FROM node:8-alpine as vault
|
||||
FROM node:9-alpine as vault
|
||||
|
||||
ENV VAULT_VERSION "v2.3.0"
|
||||
|
||||
ENV URL "https://github.com/bitwarden/web.git"
|
||||
ENV VAULT_VERSION "1.26.0"
|
||||
ENV URL "https://github.com/bitwarden/web/archive/v${VAULT_VERSION}.tar.gz"
|
||||
|
||||
RUN apk add --update-cache --upgrade \
|
||||
curl \
|
||||
git \
|
||||
tar
|
||||
tar \
|
||||
&& npm install -g \
|
||||
gulp-cli \
|
||||
gulp
|
||||
|
||||
RUN mkdir /web-build \
|
||||
&& cd /web-build \
|
||||
&& curl -L "${URL}" | tar -xvz --strip-components=1
|
||||
|
||||
RUN git clone -b $VAULT_VERSION --depth 1 $URL web-build
|
||||
WORKDIR /web-build
|
||||
|
||||
COPY /docker/set-vault-baseurl.patch /web-build/
|
||||
RUN git apply set-vault-baseurl.patch
|
||||
COPY /docker/settings.Production.json /web-build/
|
||||
|
||||
RUN npm run sub:init && npm install
|
||||
|
||||
RUN npm run dist \
|
||||
&& mv build /web-vault
|
||||
RUN git config --global url."https://github.com/".insteadOf ssh://git@github.com/ \
|
||||
&& npm install \
|
||||
&& gulp dist:selfHosted \
|
||||
&& mv dist /web-vault
|
||||
|
||||
########################## BUILD IMAGE ##########################
|
||||
# We need to use the Rust build image, because
|
||||
# we need the Rust compiler and Cargo tooling
|
||||
FROM rust as build
|
||||
FROM rustlang/rust:nightly as build
|
||||
|
||||
# Using bundled SQLite, no need to install it
|
||||
# RUN apt-get update && apt-get install -y\
|
||||
@@ -42,7 +46,6 @@ WORKDIR /app
|
||||
# Copies over *only* your manifests and vendored dependencies
|
||||
COPY ./Cargo.* ./
|
||||
COPY ./libs ./libs
|
||||
COPY ./rust-toolchain ./rust-toolchain
|
||||
|
||||
# Builds your dependencies and removes the
|
||||
# dummy project, except the target folder
|
||||
@@ -63,27 +66,23 @@ RUN cargo build --release
|
||||
# because we already have a binary built
|
||||
FROM debian:stretch-slim
|
||||
|
||||
ENV ROCKET_ENV "staging"
|
||||
ENV ROCKET_WORKERS=10
|
||||
|
||||
# Install needed libraries
|
||||
RUN apt-get update && apt-get install -y\
|
||||
openssl\
|
||||
ca-certificates\
|
||||
--no-install-recommends\
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN mkdir /data
|
||||
VOLUME /data
|
||||
EXPOSE 80
|
||||
EXPOSE 3012
|
||||
|
||||
# Copies the files from the context (env file and web-vault)
|
||||
# and the binary from the "build" stage to the current stage
|
||||
COPY .env .
|
||||
COPY Rocket.toml .
|
||||
COPY --from=vault /web-vault ./web-vault
|
||||
COPY --from=build app/target/release/bitwarden_rs .
|
||||
|
||||
# Configures the startup!
|
||||
CMD ./bitwarden_rs
|
||||
# Use production to disable Rocket logging
|
||||
#CMD ROCKET_ENV=production ./bitwarden_rs
|
||||
CMD ROCKET_ENV=staging ./bitwarden_rs
|
||||
@@ -1,81 +0,0 @@
|
||||
# Using multistage build:
|
||||
# https://docs.docker.com/develop/develop-images/multistage-build/
|
||||
# https://whitfin.io/speeding-up-rust-docker-builds/
|
||||
####################### VAULT BUILD IMAGE #######################
|
||||
FROM node:8-alpine as vault
|
||||
|
||||
ENV VAULT_VERSION "v2.3.0"
|
||||
|
||||
ENV URL "https://github.com/bitwarden/web.git"
|
||||
|
||||
RUN apk add --update-cache --upgrade \
|
||||
curl \
|
||||
git \
|
||||
tar
|
||||
|
||||
RUN git clone -b $VAULT_VERSION --depth 1 $URL web-build
|
||||
WORKDIR /web-build
|
||||
|
||||
COPY /docker/set-vault-baseurl.patch /web-build/
|
||||
RUN git apply set-vault-baseurl.patch
|
||||
|
||||
RUN npm run sub:init && npm install
|
||||
|
||||
RUN npm run dist \
|
||||
&& mv build /web-vault
|
||||
|
||||
########################## BUILD IMAGE ##########################
|
||||
# Musl build image for statically compiled binary
|
||||
FROM clux/muslrust:nightly-2018-08-24 as build
|
||||
|
||||
# Creates a dummy project used to grab dependencies
|
||||
RUN USER=root cargo init --bin
|
||||
|
||||
# Copies over *only* your manifests and vendored dependencies
|
||||
COPY ./Cargo.* ./
|
||||
COPY ./libs ./libs
|
||||
COPY ./rust-toolchain ./rust-toolchain
|
||||
|
||||
# Builds your dependencies and removes the
|
||||
# dummy project, except the target folder
|
||||
# This folder contains the compiled dependencies
|
||||
RUN cargo build --release
|
||||
RUN find . -not -path "./target*" -delete
|
||||
|
||||
# Copies the complete project
|
||||
# To avoid copying unneeded files, use .dockerignore
|
||||
COPY . .
|
||||
|
||||
# Builds again, this time it'll just be
|
||||
# your actual source files being built
|
||||
RUN cargo build --release
|
||||
|
||||
######################## RUNTIME IMAGE ########################
|
||||
# Create a new stage with a minimal image
|
||||
# because we already have a binary built
|
||||
FROM alpine:3.8
|
||||
|
||||
ENV ROCKET_ENV "staging"
|
||||
ENV ROCKET_WORKERS=10
|
||||
ENV SSL_CERT_DIR=/etc/ssl/certs
|
||||
|
||||
# Install needed libraries
|
||||
RUN apk add \
|
||||
openssl\
|
||||
ca-certificates \
|
||||
&& rm /var/cache/apk/*
|
||||
|
||||
RUN mkdir /data
|
||||
VOLUME /data
|
||||
EXPOSE 80
|
||||
EXPOSE 3012
|
||||
|
||||
# Copies the files from the context (env file and web-vault)
|
||||
# and the binary from the "build" stage to the current stage
|
||||
COPY .env .
|
||||
COPY Rocket.toml .
|
||||
COPY --from=vault /web-vault ./web-vault
|
||||
COPY --from=build /volume/target/x86_64-unknown-linux-musl/release/bitwarden_rs .
|
||||
|
||||
# Configures the startup!
|
||||
CMD ./bitwarden_rs
|
||||
@@ -1,113 +0,0 @@
|
||||
# Using multistage build:
|
||||
# https://docs.docker.com/develop/develop-images/multistage-build/
|
||||
# https://whitfin.io/speeding-up-rust-docker-builds/
|
||||
####################### VAULT BUILD IMAGE #######################
|
||||
FROM node:8-alpine as vault
|
||||
|
||||
ENV VAULT_VERSION "v2.3.0"
|
||||
|
||||
ENV URL "https://github.com/bitwarden/web.git"
|
||||
|
||||
RUN apk add --update-cache --upgrade \
|
||||
curl \
|
||||
git \
|
||||
tar
|
||||
|
||||
RUN git clone -b $VAULT_VERSION --depth 1 $URL web-build
|
||||
WORKDIR /web-build
|
||||
|
||||
COPY /docker/set-vault-baseurl.patch /web-build/
|
||||
RUN git apply set-vault-baseurl.patch
|
||||
|
||||
RUN npm run sub:init && npm install
|
||||
|
||||
RUN npm run dist \
|
||||
&& mv build /web-vault
|
||||
|
||||
########################## BUILD IMAGE ##########################
|
||||
# We need to use the Rust build image, because
|
||||
# we need the Rust compiler and Cargo tooling
|
||||
FROM rust as build
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y \
|
||||
gcc-arm-linux-gnueabihf \
|
||||
&& mkdir -p ~/.cargo \
|
||||
&& echo '[target.armv7-unknown-linux-gnueabihf]' >> ~/.cargo/config \
|
||||
&& echo 'linker = "arm-linux-gnueabihf-gcc"' >> ~/.cargo/config
|
||||
|
||||
ENV CARGO_HOME "/root/.cargo"
|
||||
ENV USER "root"
|
||||
|
||||
# Creates a dummy project used to grab dependencies
|
||||
RUN USER=root cargo new --bin app
|
||||
WORKDIR /app
|
||||
|
||||
# Copies over *only* your manifests and vendored dependencies
|
||||
COPY ./Cargo.* ./
|
||||
COPY ./libs ./libs
|
||||
COPY ./rust-toolchain ./rust-toolchain
|
||||
|
||||
# Prepare openssl armhf libs
|
||||
RUN sed 's/^deb/deb-src/' /etc/apt/sources.list > \
|
||||
/etc/apt/sources.list.d/deb-src.list \
|
||||
&& dpkg --add-architecture armhf \
|
||||
&& apt-get update \
|
||||
&& apt-get install -y \
|
||||
libssl-dev:armhf \
|
||||
libc6-dev:armhf
|
||||
|
||||
ENV CC_armv7_unknown_linux_gnueabihf="/usr/bin/arm-linux-gnueabihf-gcc"
|
||||
ENV CROSS_COMPILE="1"
|
||||
ENV OPENSSL_INCLUDE_DIR="/usr/include/arm-linux-gnueabihf"
|
||||
ENV OPENSSL_LIB_DIR="/usr/lib/arm-linux-gnueabihf"
|
||||
|
||||
# Builds your dependencies and removes the
|
||||
# dummy project, except the target folder
|
||||
# This folder contains the compiled dependencies
|
||||
COPY . .
|
||||
RUN rustup target add armv7-unknown-linux-gnueabihf
|
||||
RUN cargo build --release --target=armv7-unknown-linux-gnueabihf -v
|
||||
RUN find . -not -path "./target*" -delete
|
||||
|
||||
# Copies the complete project
|
||||
# To avoid copying unneeded files, use .dockerignore
|
||||
COPY . .
|
||||
|
||||
# Builds again, this time it'll just be
|
||||
# your actual source files being built
|
||||
RUN cargo build --release --target=armv7-unknown-linux-gnueabihf -v
|
||||
|
||||
######################## RUNTIME IMAGE ########################
|
||||
# Create a new stage with a minimal image
|
||||
# because we already have a binary built
|
||||
FROM resin/armv7hf-debian:stretch
|
||||
|
||||
ENV ROCKET_ENV "staging"
|
||||
ENV ROCKET_WORKERS=10
|
||||
|
||||
RUN [ "cross-build-start" ]
|
||||
|
||||
# Install needed libraries
|
||||
RUN apt-get update && apt-get install -y\
|
||||
openssl\
|
||||
ca-certificates\
|
||||
--no-install-recommends\
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN mkdir /data
|
||||
|
||||
RUN [ "cross-build-end" ]
|
||||
|
||||
VOLUME /data
|
||||
EXPOSE 80
|
||||
|
||||
# Copies the files from the context (env file and web-vault)
|
||||
# and the binary from the "build" stage to the current stage
|
||||
COPY .env .
|
||||
COPY Rocket.toml .
|
||||
COPY --from=vault /web-vault ./web-vault
|
||||
COPY --from=build /app/target/armv7-unknown-linux-gnueabihf/release/bitwarden_rs .
|
||||
|
||||
# Configures the startup!
|
||||
CMD ./bitwarden_rs
|
||||
@@ -1,95 +0,0 @@
|
||||
# Proxy examples
|
||||
|
||||
In this document, `<SERVER>` refers to the IP or domain where bitwarden_rs is accessible from. If both the proxy and bitwarden_rs are running in the same system, simply use `localhost`.
|
||||
The ports proxied by default are `80` for the web server and `3012` for the WebSocket server. The proxies are configured to listen in port `443` with HTTPS enabled, which is recommended.
|
||||
|
||||
When using a proxy, it's preferrable to configure HTTPS at the proxy level and not at the application level, this way the WebSockets connection is also secured.
|
||||
|
||||
## Caddy
|
||||
|
||||
```nginx
|
||||
localhost:443 {
|
||||
# The negotiation endpoint is also proxied to Rocket
|
||||
proxy /notifications/hub/negotiate <SERVER>:80 {
|
||||
transparent
|
||||
}
|
||||
|
||||
# Notifications redirected to the websockets server
|
||||
proxy /notifications/hub <SERVER>:3012 {
|
||||
websocket
|
||||
}
|
||||
|
||||
# Proxy the Root directory to Rocket
|
||||
proxy / <SERVER>:80 {
|
||||
transparent
|
||||
}
|
||||
|
||||
tls ${SSLCERTIFICATE} ${SSLKEY}
|
||||
}
|
||||
```
|
||||
|
||||
## Nginx (by shauder)
|
||||
```nginx
|
||||
server {
|
||||
include conf.d/ssl/ssl.conf;
|
||||
|
||||
listen 443 ssl http2;
|
||||
server_name vault.*;
|
||||
|
||||
location /notifications/hub/negotiate {
|
||||
include conf.d/proxy-confs/proxy.conf;
|
||||
proxy_pass http://<SERVER>:80;
|
||||
}
|
||||
|
||||
location / {
|
||||
include conf.d/proxy-confs/proxy.conf;
|
||||
proxy_pass http://<SERVER>:80;
|
||||
}
|
||||
|
||||
location /notifications/hub {
|
||||
proxy_pass http://<SERVER>:3012;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Apache (by fbartels)
|
||||
```apache
|
||||
<VirtualHost *:443>
|
||||
SSLEngine on
|
||||
ServerName bitwarden.$hostname.$domainname
|
||||
|
||||
SSLCertificateFile ${SSLCERTIFICATE}
|
||||
SSLCertificateKeyFile ${SSLKEY}
|
||||
SSLCACertificateFile ${SSLCA}
|
||||
${SSLCHAIN}
|
||||
|
||||
ErrorLog \${APACHE_LOG_DIR}/bitwarden-error.log
|
||||
CustomLog \${APACHE_LOG_DIR}/bitwarden-access.log combined
|
||||
|
||||
RewriteEngine On
|
||||
RewriteCond %{HTTP:Upgrade} =websocket [NC]
|
||||
RewriteRule /(.*) ws://<SERVER>:3012/$1 [P,L]
|
||||
|
||||
ProxyPass / http://<SERVER>:80/
|
||||
|
||||
ProxyPreserveHost On
|
||||
ProxyRequests Off
|
||||
</VirtualHost>
|
||||
```
|
||||
|
||||
## Traefik (docker-compose example)
|
||||
```traefik
|
||||
labels:
|
||||
- 'traefik.frontend.rule=Host:vault.example.local'
|
||||
- 'traefik.docker.network=traefik'
|
||||
- 'traefik.port=80'
|
||||
- 'traefik.enable=true'
|
||||
- 'traefik.web.frontend.rule=Host:vault.example.local'
|
||||
- 'traefik.web.port=80'
|
||||
- 'traefik.hub.frontend.rule=Path:/notifications/hub'
|
||||
- 'traefik.hub.port=3012'
|
||||
- 'traefik.negotiate.frontend.rule=Path:/notifications/hub/negotiate'
|
||||
- 'traefik.negotiate.port=80'
|
||||
```
|
||||
@@ -1,2 +0,0 @@
|
||||
[global.limits]
|
||||
json = 10485760 # 10 MiB
|
||||
@@ -1,5 +0,0 @@
|
||||
# For documentation on how to configure this file,
|
||||
# see diesel.rs/guides/configuring-diesel-cli
|
||||
|
||||
[print_schema]
|
||||
file = "src/db/schema.rs"
|
||||
@@ -1,28 +0,0 @@
|
||||
--- a/src/app/services/services.module.ts
|
||||
+++ b/src/app/services/services.module.ts
|
||||
@@ -120,20 +120,17 @@ const notificationsService = new NotificationsService(userService, syncService,
|
||||
const environmentService = new EnvironmentService(apiService, storageService, notificationsService);
|
||||
const auditService = new AuditService(cryptoFunctionService, apiService);
|
||||
|
||||
-const analytics = new Analytics(window, () => platformUtilsService.isDev() || platformUtilsService.isSelfHost(),
|
||||
+const analytics = new Analytics(window, () => platformUtilsService.isDev() || platformUtilsService.isSelfHost() || true,
|
||||
platformUtilsService, storageService, appIdService);
|
||||
containerService.attachToWindow(window);
|
||||
|
||||
export function initFactory(): Function {
|
||||
return async () => {
|
||||
await (storageService as HtmlStorageService).init();
|
||||
- const isDev = platformUtilsService.isDev();
|
||||
- if (!isDev && platformUtilsService.isSelfHost()) {
|
||||
- environmentService.baseUrl = window.location.origin;
|
||||
- } else {
|
||||
- environmentService.notificationsUrl = isDev ? 'http://localhost:61840' :
|
||||
- 'https://notifications.bitwarden.com'; // window.location.origin + '/notifications';
|
||||
- }
|
||||
+ const isDev = false;
|
||||
+ environmentService.baseUrl = window.location.origin;
|
||||
+ environmentService.notificationsUrl = window.location.origin + '/notifications';
|
||||
+
|
||||
await apiService.setUrls({
|
||||
base: isDev ? null : window.location.origin,
|
||||
api: isDev ? 'http://localhost:4000' : null,
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"appSettings": {
|
||||
"apiUri": "/api",
|
||||
"identityUri": "/identity",
|
||||
"iconsUri": "/icons",
|
||||
"stripeKey": "",
|
||||
"braintreeKey": ""
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
UPDATE users
|
||||
SET totp_secret = (
|
||||
SELECT twofactor.data FROM twofactor
|
||||
WHERE twofactor.type = 0
|
||||
AND twofactor.user_uuid = users.uuid
|
||||
);
|
||||
|
||||
DROP TABLE twofactor;
|
||||
@@ -1,15 +0,0 @@
|
||||
CREATE TABLE twofactor (
|
||||
uuid TEXT NOT NULL PRIMARY KEY,
|
||||
user_uuid TEXT NOT NULL REFERENCES users (uuid),
|
||||
type INTEGER NOT NULL,
|
||||
enabled BOOLEAN NOT NULL,
|
||||
data TEXT NOT NULL,
|
||||
|
||||
UNIQUE (user_uuid, type)
|
||||
);
|
||||
|
||||
|
||||
INSERT INTO twofactor (uuid, user_uuid, type, enabled, data)
|
||||
SELECT lower(hex(randomblob(16))) , uuid, 0, 1, u.totp_secret FROM users u where u.totp_secret IS NOT NULL;
|
||||
|
||||
UPDATE users SET totp_secret = NULL; -- Instead of recreating the table, just leave the columns empty
|
||||
@@ -1,3 +0,0 @@
|
||||
ALTER TABLE ciphers
|
||||
ADD COLUMN
|
||||
password_history TEXT;
|
||||
@@ -1 +0,0 @@
|
||||
DROP TABLE invitations;
|
||||
@@ -1,3 +0,0 @@
|
||||
CREATE TABLE invitations (
|
||||
email TEXT NOT NULL PRIMARY KEY
|
||||
);
|
||||
@@ -1,7 +0,0 @@
|
||||
ALTER TABLE users
|
||||
ADD COLUMN
|
||||
client_kdf_type INTEGER NOT NULL DEFAULT 0; -- PBKDF2
|
||||
|
||||
ALTER TABLE users
|
||||
ADD COLUMN
|
||||
client_kdf_iter INTEGER NOT NULL DEFAULT 5000;
|
||||
@@ -1 +0,0 @@
|
||||
nightly-2018-09-12
|
||||
+18
-192
@@ -3,10 +3,10 @@ use rocket_contrib::Json;
|
||||
use db::DbConn;
|
||||
use db::models::*;
|
||||
|
||||
use api::{PasswordData, JsonResult, EmptyResult, JsonUpcase, NumberOrString};
|
||||
use api::{PasswordData, JsonResult, EmptyResult, JsonUpcase};
|
||||
use auth::Headers;
|
||||
use fast_chemail::is_valid_email;
|
||||
use mail;
|
||||
|
||||
use util;
|
||||
|
||||
use CONFIG;
|
||||
|
||||
@@ -14,9 +14,8 @@ use CONFIG;
|
||||
#[allow(non_snake_case)]
|
||||
struct RegisterData {
|
||||
Email: String,
|
||||
Kdf: Option<i32>,
|
||||
KdfIterations: Option<i32>,
|
||||
Key: String,
|
||||
#[serde(deserialize_with = "util::upcase_deserialize")]
|
||||
Keys: Option<KeysData>,
|
||||
MasterPasswordHash: String,
|
||||
MasterPasswordHint: Option<String>,
|
||||
@@ -34,40 +33,15 @@ struct KeysData {
|
||||
fn register(data: JsonUpcase<RegisterData>, conn: DbConn) -> EmptyResult {
|
||||
let data: RegisterData = data.into_inner().data;
|
||||
|
||||
|
||||
let mut user = match User::find_by_mail(&data.Email, &conn) {
|
||||
Some(mut user) => {
|
||||
if Invitation::take(&data.Email, &conn) {
|
||||
for mut user_org in UserOrganization::find_invited_by_user(&user.uuid, &conn).iter_mut() {
|
||||
user_org.status = UserOrgStatus::Accepted as i32;
|
||||
user_org.save(&conn);
|
||||
};
|
||||
user
|
||||
} else if CONFIG.signups_allowed {
|
||||
err!("Account with this email already exists")
|
||||
} else {
|
||||
err!("Registration not allowed")
|
||||
}
|
||||
},
|
||||
None => {
|
||||
if CONFIG.signups_allowed || Invitation::take(&data.Email, &conn) {
|
||||
User::new(data.Email)
|
||||
} else {
|
||||
err!("Registration not allowed")
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(client_kdf_iter) = data.KdfIterations {
|
||||
user.client_kdf_iter = client_kdf_iter;
|
||||
if !CONFIG.signups_allowed {
|
||||
err!(format!("Signups not allowed"))
|
||||
}
|
||||
|
||||
if let Some(client_kdf_type) = data.Kdf {
|
||||
user.client_kdf_type = client_kdf_type;
|
||||
if let Some(_) = User::find_by_mail(&data.Email, &conn) {
|
||||
err!("Email already exists")
|
||||
}
|
||||
|
||||
user.set_password(&data.MasterPasswordHash);
|
||||
user.key = data.Key;
|
||||
let mut user = User::new(data.Email, data.Key, data.MasterPasswordHash);
|
||||
|
||||
// Add extra fields if present
|
||||
if let Some(name) = data.Name {
|
||||
@@ -93,36 +67,6 @@ fn profile(headers: Headers, conn: DbConn) -> JsonResult {
|
||||
Ok(Json(headers.user.to_json(&conn)))
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
#[allow(non_snake_case)]
|
||||
struct ProfileData {
|
||||
#[serde(rename = "Culture")]
|
||||
_Culture: String, // Ignored, always use en-US
|
||||
MasterPasswordHint: Option<String>,
|
||||
Name: String,
|
||||
}
|
||||
|
||||
#[put("/accounts/profile", data = "<data>")]
|
||||
fn put_profile(data: JsonUpcase<ProfileData>, headers: Headers, conn: DbConn) -> JsonResult {
|
||||
post_profile(data, headers, conn)
|
||||
}
|
||||
|
||||
#[post("/accounts/profile", data = "<data>")]
|
||||
fn post_profile(data: JsonUpcase<ProfileData>, headers: Headers, conn: DbConn) -> JsonResult {
|
||||
let data: ProfileData = data.into_inner().data;
|
||||
|
||||
let mut user = headers.user;
|
||||
|
||||
user.name = data.Name;
|
||||
user.password_hint = match data.MasterPasswordHint {
|
||||
Some(ref h) if h.is_empty() => None,
|
||||
_ => data.MasterPasswordHint,
|
||||
};
|
||||
user.save(&conn);
|
||||
|
||||
Ok(Json(user.to_json(&conn)))
|
||||
}
|
||||
|
||||
#[get("/users/<uuid>/public-key")]
|
||||
fn get_public_keys(uuid: String, _headers: Headers, conn: DbConn) -> JsonResult {
|
||||
let user = match User::find_by_uuid(&uuid, &conn) {
|
||||
@@ -175,35 +119,6 @@ fn post_password(data: JsonUpcase<ChangePassData>, headers: Headers, conn: DbCon
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[allow(non_snake_case)]
|
||||
struct ChangeKdfData {
|
||||
Kdf: i32,
|
||||
KdfIterations: i32,
|
||||
|
||||
MasterPasswordHash: String,
|
||||
NewMasterPasswordHash: String,
|
||||
Key: String,
|
||||
}
|
||||
|
||||
#[post("/accounts/kdf", data = "<data>")]
|
||||
fn post_kdf(data: JsonUpcase<ChangeKdfData>, headers: Headers, conn: DbConn) -> EmptyResult {
|
||||
let data: ChangeKdfData = data.into_inner().data;
|
||||
let mut user = headers.user;
|
||||
|
||||
if !user.check_valid_password(&data.MasterPasswordHash) {
|
||||
err!("Invalid password")
|
||||
}
|
||||
|
||||
user.client_kdf_iter = data.KdfIterations;
|
||||
user.client_kdf_type = data.Kdf;
|
||||
user.set_password(&data.NewMasterPasswordHash);
|
||||
user.key = data.Key;
|
||||
user.save(&conn);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[post("/accounts/security-stamp", data = "<data>")]
|
||||
fn post_sstamp(data: JsonUpcase<PasswordData>, headers: Headers, conn: DbConn) -> EmptyResult {
|
||||
let data: PasswordData = data.into_inner().data;
|
||||
@@ -219,41 +134,15 @@ fn post_sstamp(data: JsonUpcase<PasswordData>, headers: Headers, conn: DbConn) -
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[allow(non_snake_case)]
|
||||
struct EmailTokenData {
|
||||
MasterPasswordHash: String,
|
||||
NewEmail: String,
|
||||
}
|
||||
|
||||
#[post("/accounts/email-token", data = "<data>")]
|
||||
fn post_email_token(data: JsonUpcase<EmailTokenData>, headers: Headers, conn: DbConn) -> EmptyResult {
|
||||
let data: EmailTokenData = data.into_inner().data;
|
||||
|
||||
if !headers.user.check_valid_password(&data.MasterPasswordHash) {
|
||||
err!("Invalid password")
|
||||
}
|
||||
|
||||
if User::find_by_mail(&data.NewEmail, &conn).is_some() {
|
||||
err!("Email already in use");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[allow(non_snake_case)]
|
||||
struct ChangeEmailData {
|
||||
MasterPasswordHash: String,
|
||||
NewEmail: String,
|
||||
|
||||
Key: String,
|
||||
NewMasterPasswordHash: String,
|
||||
#[serde(rename = "Token")]
|
||||
_Token: NumberOrString,
|
||||
}
|
||||
|
||||
#[post("/accounts/email", data = "<data>")]
|
||||
|
||||
#[post("/accounts/email-token", data = "<data>")]
|
||||
fn post_email(data: JsonUpcase<ChangeEmailData>, headers: Headers, conn: DbConn) -> EmptyResult {
|
||||
let data: ChangeEmailData = data.into_inner().data;
|
||||
let mut user = headers.user;
|
||||
@@ -267,21 +156,12 @@ fn post_email(data: JsonUpcase<ChangeEmailData>, headers: Headers, conn: DbConn)
|
||||
}
|
||||
|
||||
user.email = data.NewEmail;
|
||||
|
||||
user.set_password(&data.NewMasterPasswordHash);
|
||||
user.key = data.Key;
|
||||
|
||||
user.save(&conn);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[post("/accounts/delete", data = "<data>")]
|
||||
fn post_delete_account(data: JsonUpcase<PasswordData>, headers: Headers, conn: DbConn) -> EmptyResult {
|
||||
delete_account(data, headers, conn)
|
||||
}
|
||||
|
||||
#[delete("/accounts", data = "<data>")]
|
||||
fn delete_account(data: JsonUpcase<PasswordData>, headers: Headers, conn: DbConn) -> EmptyResult {
|
||||
let data: PasswordData = data.into_inner().data;
|
||||
let user = headers.user;
|
||||
@@ -292,15 +172,17 @@ fn delete_account(data: JsonUpcase<PasswordData>, headers: Headers, conn: DbConn
|
||||
|
||||
// Delete ciphers and their attachments
|
||||
for cipher in Cipher::find_owned_by_user(&user.uuid, &conn) {
|
||||
if cipher.delete(&conn).is_err() {
|
||||
err!("Failed deleting cipher")
|
||||
match cipher.delete(&conn) {
|
||||
Ok(()) => (),
|
||||
Err(_) => err!("Failed deleting cipher")
|
||||
}
|
||||
}
|
||||
|
||||
// Delete folders
|
||||
for f in Folder::find_by_user(&user.uuid, &conn) {
|
||||
if f.delete(&conn).is_err() {
|
||||
err!("Failed deleting folder")
|
||||
match f.delete(&conn) {
|
||||
Ok(()) => (),
|
||||
Err(_) => err!("Failed deleting folder")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -315,62 +197,6 @@ fn delete_account(data: JsonUpcase<PasswordData>, headers: Headers, conn: DbConn
|
||||
|
||||
#[get("/accounts/revision-date")]
|
||||
fn revision_date(headers: Headers) -> String {
|
||||
let revision_date = headers.user.updated_at.timestamp_millis();
|
||||
let revision_date = headers.user.updated_at.timestamp();
|
||||
revision_date.to_string()
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[allow(non_snake_case)]
|
||||
struct PasswordHintData {
|
||||
Email: String,
|
||||
}
|
||||
|
||||
#[post("/accounts/password-hint", data = "<data>")]
|
||||
fn password_hint(data: JsonUpcase<PasswordHintData>, conn: DbConn) -> EmptyResult {
|
||||
let data: PasswordHintData = data.into_inner().data;
|
||||
|
||||
if !is_valid_email(&data.Email) {
|
||||
err!("This email address is not valid...");
|
||||
}
|
||||
|
||||
let user = User::find_by_mail(&data.Email, &conn);
|
||||
if user.is_none() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let user = user.unwrap();
|
||||
if let Some(ref mail_config) = CONFIG.mail {
|
||||
if let Err(e) = mail::send_password_hint(&user.email, user.password_hint, mail_config) {
|
||||
err!(format!("There have been a problem sending the email: {}", e));
|
||||
}
|
||||
} else if CONFIG.show_password_hint {
|
||||
if let Some(hint) = user.password_hint {
|
||||
err!(format!("Your password hint is: {}", &hint));
|
||||
} else {
|
||||
err!("Sorry, you have no password hint...");
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[allow(non_snake_case)]
|
||||
struct PreloginData {
|
||||
Email: String,
|
||||
}
|
||||
|
||||
#[post("/accounts/prelogin", data = "<data>")]
|
||||
fn prelogin(data: JsonUpcase<PreloginData>, conn: DbConn) -> JsonResult {
|
||||
let data: PreloginData = data.into_inner().data;
|
||||
|
||||
let (kdf_type, kdf_iter) = match User::find_by_mail(&data.Email, &conn) {
|
||||
Some(user) => (user.client_kdf_type, user.client_kdf_iter),
|
||||
None => (User::CLIENT_KDF_TYPE_DEFAULT, User::CLIENT_KDF_ITER_DEFAULT),
|
||||
};
|
||||
|
||||
Ok(Json(json!({
|
||||
"Kdf": kdf_type,
|
||||
"KdfIterations": kdf_iter
|
||||
})))
|
||||
}
|
||||
|
||||
+139
-262
File diff suppressed because it is too large
Load Diff
+9
-15
@@ -1,10 +1,9 @@
|
||||
use rocket::State;
|
||||
use rocket_contrib::{Json, Value};
|
||||
|
||||
use db::DbConn;
|
||||
use db::models::*;
|
||||
|
||||
use api::{JsonResult, EmptyResult, JsonUpcase, WebSocketUsers, UpdateType};
|
||||
use api::{JsonResult, EmptyResult, JsonUpcase};
|
||||
use auth::Headers;
|
||||
|
||||
#[get("/folders")]
|
||||
@@ -41,24 +40,23 @@ pub struct FolderData {
|
||||
}
|
||||
|
||||
#[post("/folders", data = "<data>")]
|
||||
fn post_folders(data: JsonUpcase<FolderData>, headers: Headers, conn: DbConn, ws: State<WebSocketUsers>) -> JsonResult {
|
||||
fn post_folders(data: JsonUpcase<FolderData>, headers: Headers, conn: DbConn) -> JsonResult {
|
||||
let data: FolderData = data.into_inner().data;
|
||||
|
||||
let mut folder = Folder::new(headers.user.uuid.clone(), data.Name);
|
||||
|
||||
folder.save(&conn);
|
||||
ws.send_folder_update(UpdateType::SyncFolderCreate, &folder);
|
||||
|
||||
Ok(Json(folder.to_json()))
|
||||
}
|
||||
|
||||
#[post("/folders/<uuid>", data = "<data>")]
|
||||
fn post_folder(uuid: String, data: JsonUpcase<FolderData>, headers: Headers, conn: DbConn, ws: State<WebSocketUsers>) -> JsonResult {
|
||||
put_folder(uuid, data, headers, conn, ws)
|
||||
fn post_folder(uuid: String, data: JsonUpcase<FolderData>, headers: Headers, conn: DbConn) -> JsonResult {
|
||||
put_folder(uuid, data, headers, conn)
|
||||
}
|
||||
|
||||
#[put("/folders/<uuid>", data = "<data>")]
|
||||
fn put_folder(uuid: String, data: JsonUpcase<FolderData>, headers: Headers, conn: DbConn, ws: State<WebSocketUsers>) -> JsonResult {
|
||||
fn put_folder(uuid: String, data: JsonUpcase<FolderData>, headers: Headers, conn: DbConn) -> JsonResult {
|
||||
let data: FolderData = data.into_inner().data;
|
||||
|
||||
let mut folder = match Folder::find_by_uuid(&uuid, &conn) {
|
||||
@@ -73,18 +71,17 @@ fn put_folder(uuid: String, data: JsonUpcase<FolderData>, headers: Headers, conn
|
||||
folder.name = data.Name;
|
||||
|
||||
folder.save(&conn);
|
||||
ws.send_folder_update(UpdateType::SyncFolderUpdate, &folder);
|
||||
|
||||
Ok(Json(folder.to_json()))
|
||||
}
|
||||
|
||||
#[post("/folders/<uuid>/delete")]
|
||||
fn delete_folder_post(uuid: String, headers: Headers, conn: DbConn, ws: State<WebSocketUsers>) -> EmptyResult {
|
||||
delete_folder(uuid, headers, conn, ws)
|
||||
fn delete_folder_post(uuid: String, headers: Headers, conn: DbConn) -> EmptyResult {
|
||||
delete_folder(uuid, headers, conn)
|
||||
}
|
||||
|
||||
#[delete("/folders/<uuid>")]
|
||||
fn delete_folder(uuid: String, headers: Headers, conn: DbConn, ws: State<WebSocketUsers>) -> EmptyResult {
|
||||
fn delete_folder(uuid: String, headers: Headers, conn: DbConn) -> EmptyResult {
|
||||
let folder = match Folder::find_by_uuid(&uuid, &conn) {
|
||||
Some(folder) => folder,
|
||||
_ => err!("Invalid folder")
|
||||
@@ -96,10 +93,7 @@ fn delete_folder(uuid: String, headers: Headers, conn: DbConn, ws: State<WebSock
|
||||
|
||||
// Delete the actual folder entry
|
||||
match folder.delete(&conn) {
|
||||
Ok(()) => {
|
||||
ws.send_folder_update(UpdateType::SyncFolderDelete, &folder);
|
||||
Ok(())
|
||||
}
|
||||
Ok(()) => Ok(()),
|
||||
Err(_) => err!("Failed deleting folder")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -646,121 +646,5 @@
|
||||
"wiktionary.org"
|
||||
],
|
||||
"Excluded": false
|
||||
},
|
||||
{
|
||||
"Type": 72,
|
||||
"Domains": [
|
||||
"airbnb.at",
|
||||
"airbnb.be",
|
||||
"airbnb.ca",
|
||||
"airbnb.ch",
|
||||
"airbnb.cl",
|
||||
"airbnb.co.cr",
|
||||
"airbnb.co.id",
|
||||
"airbnb.co.in",
|
||||
"airbnb.co.kr",
|
||||
"airbnb.co.nz",
|
||||
"airbnb.co.uk",
|
||||
"airbnb.co.ve",
|
||||
"airbnb.com",
|
||||
"airbnb.com.ar",
|
||||
"airbnb.com.au",
|
||||
"airbnb.com.bo",
|
||||
"airbnb.com.br",
|
||||
"airbnb.com.bz",
|
||||
"airbnb.com.co",
|
||||
"airbnb.com.ec",
|
||||
"airbnb.com.gt",
|
||||
"airbnb.com.hk",
|
||||
"airbnb.com.hn",
|
||||
"airbnb.com.mt",
|
||||
"airbnb.com.my",
|
||||
"airbnb.com.ni",
|
||||
"airbnb.com.pa",
|
||||
"airbnb.com.pe",
|
||||
"airbnb.com.py",
|
||||
"airbnb.com.sg",
|
||||
"airbnb.com.sv",
|
||||
"airbnb.com.tr",
|
||||
"airbnb.com.tw",
|
||||
"airbnb.cz",
|
||||
"airbnb.de",
|
||||
"airbnb.dk",
|
||||
"airbnb.es",
|
||||
"airbnb.fi",
|
||||
"airbnb.fr",
|
||||
"airbnb.gr",
|
||||
"airbnb.gy",
|
||||
"airbnb.hu",
|
||||
"airbnb.ie",
|
||||
"airbnb.is",
|
||||
"airbnb.it",
|
||||
"airbnb.jp",
|
||||
"airbnb.mx",
|
||||
"airbnb.nl",
|
||||
"airbnb.no",
|
||||
"airbnb.pl",
|
||||
"airbnb.pt",
|
||||
"airbnb.ru",
|
||||
"airbnb.se"
|
||||
],
|
||||
"Excluded": false
|
||||
},
|
||||
{
|
||||
"Type": 73,
|
||||
"Domains": [
|
||||
"eventbrite.at",
|
||||
"eventbrite.be",
|
||||
"eventbrite.ca",
|
||||
"eventbrite.ch",
|
||||
"eventbrite.cl",
|
||||
"eventbrite.co.id",
|
||||
"eventbrite.co.in",
|
||||
"eventbrite.co.kr",
|
||||
"eventbrite.co.nz",
|
||||
"eventbrite.co.uk",
|
||||
"eventbrite.co.ve",
|
||||
"eventbrite.com",
|
||||
"eventbrite.com.au",
|
||||
"eventbrite.com.bo",
|
||||
"eventbrite.com.br",
|
||||
"eventbrite.com.co",
|
||||
"eventbrite.com.hk",
|
||||
"eventbrite.com.hn",
|
||||
"eventbrite.com.pe",
|
||||
"eventbrite.com.sg",
|
||||
"eventbrite.com.tr",
|
||||
"eventbrite.com.tw",
|
||||
"eventbrite.cz",
|
||||
"eventbrite.de",
|
||||
"eventbrite.dk",
|
||||
"eventbrite.fi",
|
||||
"eventbrite.fr",
|
||||
"eventbrite.gy",
|
||||
"eventbrite.hu",
|
||||
"eventbrite.ie",
|
||||
"eventbrite.is",
|
||||
"eventbrite.it",
|
||||
"eventbrite.jp",
|
||||
"eventbrite.mx",
|
||||
"eventbrite.nl",
|
||||
"eventbrite.no",
|
||||
"eventbrite.pl",
|
||||
"eventbrite.pt",
|
||||
"eventbrite.ru",
|
||||
"eventbrite.se"
|
||||
],
|
||||
"Excluded": false
|
||||
},
|
||||
{
|
||||
"Type": 74,
|
||||
"Domains": [
|
||||
"stackexchange.com",
|
||||
"superuser.com",
|
||||
"stackoverflow.com",
|
||||
"serverfault.com",
|
||||
"mathoverflow.net"
|
||||
],
|
||||
"Excluded": false
|
||||
}
|
||||
]
|
||||
+10
-41
@@ -2,7 +2,7 @@ mod accounts;
|
||||
mod ciphers;
|
||||
mod folders;
|
||||
mod organizations;
|
||||
pub(crate) mod two_factor;
|
||||
mod two_factor;
|
||||
|
||||
use self::accounts::*;
|
||||
use self::ciphers::*;
|
||||
@@ -14,20 +14,13 @@ pub fn routes() -> Vec<Route> {
|
||||
routes![
|
||||
register,
|
||||
profile,
|
||||
put_profile,
|
||||
post_profile,
|
||||
get_public_keys,
|
||||
post_keys,
|
||||
post_password,
|
||||
post_kdf,
|
||||
post_sstamp,
|
||||
post_email_token,
|
||||
post_email,
|
||||
delete_account,
|
||||
post_delete_account,
|
||||
revision_date,
|
||||
password_hint,
|
||||
prelogin,
|
||||
|
||||
sync,
|
||||
|
||||
@@ -36,31 +29,20 @@ pub fn routes() -> Vec<Route> {
|
||||
get_cipher_admin,
|
||||
get_cipher_details,
|
||||
post_ciphers,
|
||||
put_cipher_admin,
|
||||
post_ciphers_admin,
|
||||
post_ciphers_import,
|
||||
post_attachment,
|
||||
post_attachment_admin,
|
||||
post_attachment_share,
|
||||
delete_attachment_post,
|
||||
delete_attachment_post_admin,
|
||||
delete_attachment,
|
||||
delete_attachment_admin,
|
||||
post_cipher_admin,
|
||||
post_cipher_share,
|
||||
put_cipher_share,
|
||||
put_cipher_share_seleted,
|
||||
post_cipher,
|
||||
put_cipher,
|
||||
delete_cipher_post,
|
||||
delete_cipher_post_admin,
|
||||
delete_cipher,
|
||||
delete_cipher_admin,
|
||||
delete_cipher_selected,
|
||||
delete_cipher_selected_post,
|
||||
delete_all,
|
||||
move_cipher_selected,
|
||||
move_cipher_selected_put,
|
||||
|
||||
get_folders,
|
||||
get_folder,
|
||||
@@ -73,46 +55,31 @@ pub fn routes() -> Vec<Route> {
|
||||
get_twofactor,
|
||||
get_recover,
|
||||
recover,
|
||||
disable_twofactor,
|
||||
disable_twofactor_put,
|
||||
generate_authenticator,
|
||||
activate_authenticator,
|
||||
activate_authenticator_put,
|
||||
generate_u2f,
|
||||
activate_u2f,
|
||||
activate_u2f_put,
|
||||
disable_authenticator,
|
||||
|
||||
get_organization,
|
||||
create_organization,
|
||||
delete_organization,
|
||||
post_delete_organization,
|
||||
leave_organization,
|
||||
get_user_collections,
|
||||
get_org_collections,
|
||||
get_org_collection_detail,
|
||||
get_collection_users,
|
||||
put_organization,
|
||||
post_organization,
|
||||
post_organization_collections,
|
||||
delete_organization_collection_user,
|
||||
post_organization_collection_delete_user,
|
||||
post_organization_collection_update,
|
||||
put_organization_collection_update,
|
||||
delete_organization_collection,
|
||||
post_organization_collection_delete,
|
||||
post_collections_update,
|
||||
post_collections_admin,
|
||||
put_collections_admin,
|
||||
get_org_details,
|
||||
get_org_users,
|
||||
send_invite,
|
||||
confirm_invite,
|
||||
get_user,
|
||||
edit_user,
|
||||
put_organization_user,
|
||||
delete_user,
|
||||
post_delete_user,
|
||||
post_org_import,
|
||||
|
||||
clear_device_token,
|
||||
put_device_token,
|
||||
@@ -139,7 +106,8 @@ use auth::Headers;
|
||||
|
||||
#[put("/devices/identifier/<uuid>/clear-token", data = "<data>")]
|
||||
fn clear_device_token(uuid: String, data: Json<Value>, headers: Headers, conn: DbConn) -> EmptyResult {
|
||||
let _data: Value = data.into_inner();
|
||||
println!("UUID: {:#?}", uuid);
|
||||
println!("DATA: {:#?}", data);
|
||||
|
||||
let device = match Device::find_by_uuid(&uuid, &conn) {
|
||||
Some(device) => device,
|
||||
@@ -157,8 +125,9 @@ fn clear_device_token(uuid: String, data: Json<Value>, headers: Headers, conn: D
|
||||
|
||||
#[put("/devices/identifier/<uuid>/token", data = "<data>")]
|
||||
fn put_device_token(uuid: String, data: Json<Value>, headers: Headers, conn: DbConn) -> JsonResult {
|
||||
let _data: Value = data.into_inner();
|
||||
|
||||
println!("UUID: {:#?}", uuid);
|
||||
println!("DATA: {:#?}", data);
|
||||
|
||||
let device = match Device::find_by_uuid(&uuid, &conn) {
|
||||
Some(device) => device,
|
||||
None => err!("Device not found")
|
||||
@@ -181,7 +150,7 @@ struct GlobalDomain {
|
||||
Excluded: bool,
|
||||
}
|
||||
|
||||
const GLOBAL_DOMAINS: &str = include_str!("global_domains.json");
|
||||
const GLOBAL_DOMAINS: &'static str = include_str!("global_domains.json");
|
||||
|
||||
#[get("/settings/domains")]
|
||||
fn get_eq_domains(headers: Headers) -> JsonResult {
|
||||
@@ -216,8 +185,8 @@ struct EquivDomainData {
|
||||
fn post_eq_domains(data: JsonUpcase<EquivDomainData>, headers: Headers, conn: DbConn) -> EmptyResult {
|
||||
let data: EquivDomainData = data.into_inner().data;
|
||||
|
||||
let excluded_globals = data.ExcludedGlobalEquivalentDomains.unwrap_or_default();
|
||||
let equivalent_domains = data.EquivalentDomains.unwrap_or_default();
|
||||
let excluded_globals = data.ExcludedGlobalEquivalentDomains.unwrap_or(Vec::new());
|
||||
let equivalent_domains = data.EquivalentDomains.unwrap_or(Vec::new());
|
||||
|
||||
let mut user = headers.user;
|
||||
use serde_json::to_string;
|
||||
|
||||
+88
-234
File diff suppressed because it is too large
Load Diff
+100
-399
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user