From df69bdbc21127344b6611b59a8a675a6e94d4053 Mon Sep 17 00:00:00 2001 From: Kyle Spearrin Date: Tue, 8 Dec 2015 22:35:05 -0500 Subject: [PATCH] initial commit of source --- .gitignore | 202 ++++++++++++ NuGet.Config | 8 + README.md | 1 + bitwarden-vault.sln | 35 ++ global.json | 6 + src/Vault/Properties/AssemblyInfo.cs | 23 ++ src/Vault/Properties/launchSettings.json | 25 ++ src/Vault/Startup.cs | 21 ++ src/Vault/Vault.xproj | 19 ++ src/Vault/gulpfile.js | 312 ++++++++++++++++++ src/Vault/less/theme.less | 47 +++ src/Vault/less/vault.less | 170 ++++++++++ src/Vault/package.json | 43 +++ src/Vault/project.json | 27 ++ src/Vault/settings.Development.json | 5 + src/Vault/settings.Production.json | 5 + src/Vault/settings.Staging.json | 5 + src/Vault/settings.json | 5 + src/Vault/wwwroot/_references.js | 48 +++ .../app/accounts/accountsLoginController.js | 48 +++ .../app/accounts/accountsLogoutController.js | 7 + .../wwwroot/app/accounts/accountsModule.js | 2 + .../accountsPasswordHintController.js | 12 + .../accounts/accountsRegisterController.js | 13 + .../accountsRegisterFinalizeController.js | 48 +++ .../app/accounts/views/accountsLogin.html | 7 + .../app/accounts/views/accountsLoginInfo.html | 40 +++ .../views/accountsLoginTwoFactor.html | 22 ++ .../accounts/views/accountsPasswordHint.html | 37 +++ .../app/accounts/views/accountsRegister.html | 37 +++ .../views/accountsRegisterFinalize.html | 7 + .../accountsRegisterFinalizeConfirm.html | 35 ++ .../views/accountsRegisterFinalizeInfo.html | 35 ++ src/Vault/wwwroot/app/apiInterceptor.js | 29 ++ src/Vault/wwwroot/app/app.js | 18 + src/Vault/wwwroot/app/config.js | 157 +++++++++ .../app/directives/apiFieldDirective.js | 30 ++ .../app/directives/apiFormDirective.js | 35 ++ .../app/directives/directivesModule.js | 2 + .../app/directives/masterPasswordDirective.js | 40 +++ .../app/directives/pageTitleDirective.js | 22 ++ .../app/directives/passwordMeterDirective.js | 73 ++++ .../app/directives/passwordViewerDirective.js | 27 ++ src/Vault/wwwroot/app/global/globalModule.js | 2 + .../wwwroot/app/global/mainController.js | 78 +++++ .../wwwroot/app/global/sideNavController.js | 6 + .../wwwroot/app/global/topNavController.js | 6 + src/Vault/wwwroot/app/services/apiService.js | 48 +++ src/Vault/wwwroot/app/services/authService.js | 111 +++++++ .../wwwroot/app/services/cipherService.js | 110 ++++++ .../wwwroot/app/services/cryptoService.js | 114 +++++++ .../wwwroot/app/services/passwordService.js | 105 ++++++ .../wwwroot/app/services/servicesModule.js | 2 + .../wwwroot/app/services/tokenService.js | 27 ++ .../wwwroot/app/services/validationService.js | 52 +++ src/Vault/wwwroot/app/settings.js | 2 + .../settings/settingsChangeEmailController.js | 66 ++++ .../settingsChangePasswordController.js | 53 +++ .../app/settings/settingsController.js | 72 ++++ .../wwwroot/app/settings/settingsModule.js | 2 + .../settings/settingsSessionsController.js | 22 ++ .../settings/settingsTwoFactorController.js | 62 ++++ .../wwwroot/app/settings/views/settings.html | 46 +++ .../settings/views/settingsChangeEmail.html | 54 +++ .../views/settingsChangePassword.html | 46 +++ .../app/settings/views/settingsSessions.html | 32 ++ .../app/settings/views/settingsTwoFactor.html | 82 +++++ .../app/tools/toolsAuditsController.js | 8 + .../wwwroot/app/tools/toolsController.js | 42 +++ .../app/tools/toolsExportController.js | 71 ++++ .../app/tools/toolsImportController.js | 8 + src/Vault/wwwroot/app/tools/toolsModule.js | 2 + src/Vault/wwwroot/app/tools/views/tools.html | 9 + .../wwwroot/app/tools/views/toolsAudits.html | 10 + .../wwwroot/app/tools/views/toolsExport.html | 28 ++ .../wwwroot/app/tools/views/toolsImport.html | 21 ++ .../app/vault/vaultAddFolderController.js | 17 + .../app/vault/vaultAddSiteController.js | 47 +++ .../wwwroot/app/vault/vaultController.js | 155 +++++++++ .../app/vault/vaultEditFolderController.js | 23 ++ .../app/vault/vaultEditSiteController.js | 48 +++ src/Vault/wwwroot/app/vault/vaultModule.js | 2 + src/Vault/wwwroot/app/vault/views/vault.html | 51 +++ .../app/vault/views/vaultAddFolder.html | 24 ++ .../wwwroot/app/vault/views/vaultAddSite.html | 92 ++++++ .../app/vault/views/vaultEditFolder.html | 24 ++ .../app/vault/views/vaultEditSite.html | 95 ++++++ .../wwwroot/app/views/backendLayout.html | 78 +++++ .../wwwroot/app/views/frontendLayout.html | 2 + src/Vault/wwwroot/favicon.ico | Bin 0 -> 1150 bytes src/Vault/wwwroot/images/boxed-bg-2x.png | Bin 0 -> 84138 bytes src/Vault/wwwroot/images/boxed-bg.png | Bin 0 -> 63654 bytes src/Vault/wwwroot/index.html | 124 +++++++ src/Vault/wwwroot/web.config | 9 + 94 files changed, 3980 insertions(+) create mode 100644 .gitignore create mode 100644 NuGet.Config create mode 100644 README.md create mode 100644 bitwarden-vault.sln create mode 100644 global.json create mode 100644 src/Vault/Properties/AssemblyInfo.cs create mode 100644 src/Vault/Properties/launchSettings.json create mode 100644 src/Vault/Startup.cs create mode 100644 src/Vault/Vault.xproj create mode 100644 src/Vault/gulpfile.js create mode 100644 src/Vault/less/theme.less create mode 100644 src/Vault/less/vault.less create mode 100644 src/Vault/package.json create mode 100644 src/Vault/project.json create mode 100644 src/Vault/settings.Development.json create mode 100644 src/Vault/settings.Production.json create mode 100644 src/Vault/settings.Staging.json create mode 100644 src/Vault/settings.json create mode 100644 src/Vault/wwwroot/_references.js create mode 100644 src/Vault/wwwroot/app/accounts/accountsLoginController.js create mode 100644 src/Vault/wwwroot/app/accounts/accountsLogoutController.js create mode 100644 src/Vault/wwwroot/app/accounts/accountsModule.js create mode 100644 src/Vault/wwwroot/app/accounts/accountsPasswordHintController.js create mode 100644 src/Vault/wwwroot/app/accounts/accountsRegisterController.js create mode 100644 src/Vault/wwwroot/app/accounts/accountsRegisterFinalizeController.js create mode 100644 src/Vault/wwwroot/app/accounts/views/accountsLogin.html create mode 100644 src/Vault/wwwroot/app/accounts/views/accountsLoginInfo.html create mode 100644 src/Vault/wwwroot/app/accounts/views/accountsLoginTwoFactor.html create mode 100644 src/Vault/wwwroot/app/accounts/views/accountsPasswordHint.html create mode 100644 src/Vault/wwwroot/app/accounts/views/accountsRegister.html create mode 100644 src/Vault/wwwroot/app/accounts/views/accountsRegisterFinalize.html create mode 100644 src/Vault/wwwroot/app/accounts/views/accountsRegisterFinalizeConfirm.html create mode 100644 src/Vault/wwwroot/app/accounts/views/accountsRegisterFinalizeInfo.html create mode 100644 src/Vault/wwwroot/app/apiInterceptor.js create mode 100644 src/Vault/wwwroot/app/app.js create mode 100644 src/Vault/wwwroot/app/config.js create mode 100644 src/Vault/wwwroot/app/directives/apiFieldDirective.js create mode 100644 src/Vault/wwwroot/app/directives/apiFormDirective.js create mode 100644 src/Vault/wwwroot/app/directives/directivesModule.js create mode 100644 src/Vault/wwwroot/app/directives/masterPasswordDirective.js create mode 100644 src/Vault/wwwroot/app/directives/pageTitleDirective.js create mode 100644 src/Vault/wwwroot/app/directives/passwordMeterDirective.js create mode 100644 src/Vault/wwwroot/app/directives/passwordViewerDirective.js create mode 100644 src/Vault/wwwroot/app/global/globalModule.js create mode 100644 src/Vault/wwwroot/app/global/mainController.js create mode 100644 src/Vault/wwwroot/app/global/sideNavController.js create mode 100644 src/Vault/wwwroot/app/global/topNavController.js create mode 100644 src/Vault/wwwroot/app/services/apiService.js create mode 100644 src/Vault/wwwroot/app/services/authService.js create mode 100644 src/Vault/wwwroot/app/services/cipherService.js create mode 100644 src/Vault/wwwroot/app/services/cryptoService.js create mode 100644 src/Vault/wwwroot/app/services/passwordService.js create mode 100644 src/Vault/wwwroot/app/services/servicesModule.js create mode 100644 src/Vault/wwwroot/app/services/tokenService.js create mode 100644 src/Vault/wwwroot/app/services/validationService.js create mode 100644 src/Vault/wwwroot/app/settings.js create mode 100644 src/Vault/wwwroot/app/settings/settingsChangeEmailController.js create mode 100644 src/Vault/wwwroot/app/settings/settingsChangePasswordController.js create mode 100644 src/Vault/wwwroot/app/settings/settingsController.js create mode 100644 src/Vault/wwwroot/app/settings/settingsModule.js create mode 100644 src/Vault/wwwroot/app/settings/settingsSessionsController.js create mode 100644 src/Vault/wwwroot/app/settings/settingsTwoFactorController.js create mode 100644 src/Vault/wwwroot/app/settings/views/settings.html create mode 100644 src/Vault/wwwroot/app/settings/views/settingsChangeEmail.html create mode 100644 src/Vault/wwwroot/app/settings/views/settingsChangePassword.html create mode 100644 src/Vault/wwwroot/app/settings/views/settingsSessions.html create mode 100644 src/Vault/wwwroot/app/settings/views/settingsTwoFactor.html create mode 100644 src/Vault/wwwroot/app/tools/toolsAuditsController.js create mode 100644 src/Vault/wwwroot/app/tools/toolsController.js create mode 100644 src/Vault/wwwroot/app/tools/toolsExportController.js create mode 100644 src/Vault/wwwroot/app/tools/toolsImportController.js create mode 100644 src/Vault/wwwroot/app/tools/toolsModule.js create mode 100644 src/Vault/wwwroot/app/tools/views/tools.html create mode 100644 src/Vault/wwwroot/app/tools/views/toolsAudits.html create mode 100644 src/Vault/wwwroot/app/tools/views/toolsExport.html create mode 100644 src/Vault/wwwroot/app/tools/views/toolsImport.html create mode 100644 src/Vault/wwwroot/app/vault/vaultAddFolderController.js create mode 100644 src/Vault/wwwroot/app/vault/vaultAddSiteController.js create mode 100644 src/Vault/wwwroot/app/vault/vaultController.js create mode 100644 src/Vault/wwwroot/app/vault/vaultEditFolderController.js create mode 100644 src/Vault/wwwroot/app/vault/vaultEditSiteController.js create mode 100644 src/Vault/wwwroot/app/vault/vaultModule.js create mode 100644 src/Vault/wwwroot/app/vault/views/vault.html create mode 100644 src/Vault/wwwroot/app/vault/views/vaultAddFolder.html create mode 100644 src/Vault/wwwroot/app/vault/views/vaultAddSite.html create mode 100644 src/Vault/wwwroot/app/vault/views/vaultEditFolder.html create mode 100644 src/Vault/wwwroot/app/vault/views/vaultEditSite.html create mode 100644 src/Vault/wwwroot/app/views/backendLayout.html create mode 100644 src/Vault/wwwroot/app/views/frontendLayout.html create mode 100644 src/Vault/wwwroot/favicon.ico create mode 100644 src/Vault/wwwroot/images/boxed-bg-2x.png create mode 100644 src/Vault/wwwroot/images/boxed-bg.png create mode 100644 src/Vault/wwwroot/index.html create mode 100644 src/Vault/wwwroot/web.config diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..c91485a9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,202 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +build/ +bld/ +[Bb]in/ +[Oo]bj/ + +# Visual Studo 2015 cache/options directory +.vs/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding addin-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config + +# Windows Azure Build Output +csx/ +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Others +*.[Cc]ache +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.pfx +*.publishsettings +node_modules/ +bower_components/ +lib/ +css/ +dist/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Other +project.lock.json \ No newline at end of file diff --git a/NuGet.Config b/NuGet.Config new file mode 100644 index 00000000..c3c2967a --- /dev/null +++ b/NuGet.Config @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/README.md b/README.md new file mode 100644 index 00000000..cfd94740 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# bitwarden Vault diff --git a/bitwarden-vault.sln b/bitwarden-vault.sln new file mode 100644 index 00000000..062b1684 --- /dev/null +++ b/bitwarden-vault.sln @@ -0,0 +1,35 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.23107.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{860863C9-0436-43D4-840D-FE919C9F6FFC}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{14FE7221-D377-4AD5-9A9E-4541577CF05A}" + ProjectSection(SolutionItems) = preProject + .gitignore = .gitignore + global.json = global.json + NuGet.Config = NuGet.Config + README.md = README.md + EndProjectSection +EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Vault", "src\Vault\Vault.xproj", "{0BEBF47C-BA0B-48AC-B48C-718F94084AD5}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {0BEBF47C-BA0B-48AC-B48C-718F94084AD5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0BEBF47C-BA0B-48AC-B48C-718F94084AD5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0BEBF47C-BA0B-48AC-B48C-718F94084AD5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0BEBF47C-BA0B-48AC-B48C-718F94084AD5}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {0BEBF47C-BA0B-48AC-B48C-718F94084AD5} = {860863C9-0436-43D4-840D-FE919C9F6FFC} + EndGlobalSection +EndGlobal diff --git a/global.json b/global.json new file mode 100644 index 00000000..38c762a3 --- /dev/null +++ b/global.json @@ -0,0 +1,6 @@ +{ + "projects": [ "src", "test" ], + "sdk": { + "version": "1.0.0-rc1-final" + } +} diff --git a/src/Vault/Properties/AssemblyInfo.cs b/src/Vault/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..4e5c734e --- /dev/null +++ b/src/Vault/Properties/AssemblyInfo.cs @@ -0,0 +1,23 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Bit.Vault")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("bitwarden Vault")] +[assembly: AssemblyProduct("bitwarden Vault")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("0bebf47c-ba0b-48ac-b48c-718f94084ad5")] diff --git a/src/Vault/Properties/launchSettings.json b/src/Vault/Properties/launchSettings.json new file mode 100644 index 00000000..323b7c66 --- /dev/null +++ b/src/Vault/Properties/launchSettings.json @@ -0,0 +1,25 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:4001/", + "sslPort": 0 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "Hosting:Environment": "Development" + } + }, + "web": { + "commandName": "web", + "environmentVariables": { + "Hosting:Environment": "Development" + } + } + } +} \ No newline at end of file diff --git a/src/Vault/Startup.cs b/src/Vault/Startup.cs new file mode 100644 index 00000000..ea5f2bb9 --- /dev/null +++ b/src/Vault/Startup.cs @@ -0,0 +1,21 @@ +using System; +using Microsoft.AspNet.Builder; +using Microsoft.AspNet.Hosting; +using Microsoft.Extensions.DependencyInjection; + +namespace Bit.Vault +{ + public class Startup + { + public void ConfigureServices(IServiceCollection services) { } + + public void Configure(IApplicationBuilder app) + { + app.UseIISPlatformHandler(); + app.UseFileServer(); + } + + // Entry point for the application. + public static void Main(string[] args) => WebApplication.Run(args); + } +} diff --git a/src/Vault/Vault.xproj b/src/Vault/Vault.xproj new file mode 100644 index 00000000..a890f7f5 --- /dev/null +++ b/src/Vault/Vault.xproj @@ -0,0 +1,19 @@ + + + + 14.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + 0bebf47c-ba0b-48ac-b48c-718f94084ad5 + Bit.Vault + ..\..\artifacts\obj\$(MSBuildProjectName) + ..\..\artifacts\bin\$(MSBuildProjectName)\ + + + 2.0 + 4001 + + + \ No newline at end of file diff --git a/src/Vault/gulpfile.js b/src/Vault/gulpfile.js new file mode 100644 index 00000000..b028d4f1 --- /dev/null +++ b/src/Vault/gulpfile.js @@ -0,0 +1,312 @@ +/// + +var gulp = require('gulp'), + rimraf = require('rimraf'), + concat = require('gulp-concat'), + rename = require('gulp-rename'), + cssmin = require('gulp-cssmin'), + uglify = require('gulp-uglify'), + ghPages = require('gulp-gh-pages'), + less = require('gulp-less'), + ngAnnotate = require('gulp-ng-annotate'), + preprocess = require('gulp-preprocess'), + runSequence = require('run-sequence'), + merge = require('merge-stream'), + ngConfig = require('gulp-ng-config'), + settings = require('./settings.json'), + project = require('./project.json'), + jshint = require('gulp-jshint'), + _ = require('lodash'); + +var paths = {}; +paths.dist = '../../dist/'; +paths.webroot = './wwwroot/' +paths.js = paths.webroot + 'js/**/*.js'; +paths.minJs = paths.webroot + 'js/**/*.min.js'; +paths.concatJsDest = paths.webroot + 'js/bw.min.js'; +paths.libDir = paths.webroot + 'lib/'; +paths.npmDir = 'node_modules/'; +paths.lessDir = 'less/'; +paths.cssDir = paths.webroot + 'css/'; +paths.jsDir = paths.webroot + 'js/'; + +gulp.task('lint', function () { + return gulp.src(paths.webroot + 'app/**/*.js') + .pipe(jshint()) + .pipe(jshint.reporter('default')); +}); + +gulp.task('build', function (cb) { + return runSequence( + 'clean', + ['lib', 'less', 'settings', 'lint'], + cb); +}); + +gulp.task('clean:js', function (cb) { + return rimraf(paths.concatJsDest, cb); +}); + +gulp.task('clean:css', function (cb) { + return rimraf(paths.cssDir, cb); +}); + +gulp.task('clean:lib', function (cb) { + return rimraf(paths.libDir, cb); +}); + +gulp.task('clean', ['clean:js', 'clean:css', 'clean:lib', 'dist:clean']); + +gulp.task('min:js', ['clean:js'], function () { + return gulp.src([paths.js, '!' + paths.minJs], { base: '.' }) + .pipe(concat(paths.concatJsDest)) + .pipe(uglify()) + .pipe(gulp.dest('.')); +}); + +gulp.task('min:css', [], function () { + return gulp.src([paths.cssDir + '**/*.css', '!' + paths.cssDir + '**/*.min.css'], { base: '.' }) + .pipe(cssmin()) + .pipe(rename({ suffix: '.min' })) + .pipe(gulp.dest('.')); +}); + +gulp.task('min', ['min:js', 'min:css']); + +gulp.task('lib', ['clean:lib'], function () { + var libs = [ + { + src: [ + paths.npmDir + 'bootstrap/dist/**/*', + '!' + paths.npmDir + 'bootstrap/dist/**/npm.js', + '!' + paths.npmDir + 'bootstrap/dist/**/css/*theme*' + ], + dest: paths.libDir + 'bootstrap' + }, + { + src: paths.npmDir + 'font-awesome/css/*', + dest: paths.libDir + 'font-awesome/css' + }, + { + src: paths.npmDir + 'font-awesome/fonts/*', + dest: paths.libDir + 'font-awesome/fonts' + }, + { + src: paths.npmDir + 'jquery/dist/*.js', + dest: paths.libDir + 'jquery' + }, + { + src: paths.npmDir + 'admin-lte/dist/js/app*.js', + dest: paths.libDir + 'admin-lte/js' + }, + { + src: paths.npmDir + 'angular/angular*.js', + dest: paths.libDir + 'angular' + }, + { + src: paths.npmDir + 'angular-bootstrap-npm/dist/*tpls*.js', + dest: paths.libDir + 'angular-bootstrap' + }, + { + src: paths.npmDir + 'angular-bootstrap-show-errors/src/*.js', + dest: paths.libDir + 'angular-bootstrap-show-errors' + }, + { + src: paths.npmDir + 'angular-cookies/*cookies*.js', + dest: paths.libDir + 'angular-cookies' + }, + { + src: paths.npmDir + 'angular-jwt/dist/*.js', + dest: paths.libDir + 'angular-jwt' + }, + { + src: paths.npmDir + 'angular-md5/angular-md5*.js', + dest: paths.libDir + 'angular-md5' + }, + { + src: paths.npmDir + 'angular-resource/*resource*.js', + dest: paths.libDir + 'angular-resource' + }, + { + src: [paths.npmDir + 'angular-toastr/dist/**/*.css', paths.npmDir + 'angular-toastr/dist/**/*.js'], + dest: paths.libDir + 'angular-toastr' + }, + { + src: paths.npmDir + 'angular-ui-router/release/*.js', + dest: paths.libDir + 'angular-ui-router' + }, + { + src: paths.npmDir + 'angular-messages/*messages*.js', + dest: paths.libDir + 'angular-messages' + }, + { + src: [paths.npmDir + 'sjcl/core/cbc.js', paths.npmDir + 'sjcl/core/bitArray.js', paths.npmDir + 'sjcl/sjcl.js'], + dest: paths.libDir + 'sjcl' + }, + { + src: paths.npmDir + 'ngstorage/*.js', + dest: paths.libDir + 'ngstorage' + }, + { + src: paths.npmDir + 'papaparse/papaparse*.js', + dest: paths.libDir + 'papaparse' + }, + { + src: paths.npmDir + 'ngclipboard/dist/ngclipboard*.js', + dest: paths.libDir + 'ngclipboard' + }, + { + src: paths.npmDir + 'clipboard/dist/clipboard*.js', + dest: paths.libDir + 'clipboard' + } + ]; + + var tasks = libs.map(function (lib) { + return gulp.src(lib.src).pipe(gulp.dest(lib.dest)); + }); + + return merge(tasks); +}); + +gulp.task('settings', function () { + return config() + .pipe(gulp.dest(paths.webroot + 'app')); +}); + +function config() { + return gulp.src('./settings.json') + .pipe(ngConfig('bit', { + createModule: false, + constants: _.merge({}, { + appSettings: { + version: project.version, + environment: project.environment + } + }, require('./settings.' + project.environment + '.json') || {}) + })); +} + +gulp.task('less', function () { + return gulp.src(paths.lessDir + 'vault.less') + .pipe(less()) + .pipe(gulp.dest(paths.cssDir)); +}); + +gulp.task('watch', function () { + gulp.watch(paths.lessDir + '*.less', ['less']); + gulp.watch('./settings*.json', ['settings']); +}); + +gulp.task('dist:clean', function (cb) { + return rimraf(paths.dist, cb); +}); + +gulp.task('dist:move', function () { + var moves = [ + { + src: [ + paths.npmDir + 'bootstrap/dist/**/bootstrap.min.js', + paths.npmDir + 'bootstrap/dist/**/bootstrap.min.css', + paths.npmDir + 'bootstrap/dist/**/fonts/**/*', + ], + dest: paths.dist + 'lib/bootstrap' + }, + { + src: [ + paths.npmDir + 'font-awesome/**/font-awesome.min.css', + paths.npmDir + 'font-awesome/**/fonts/**/*' + ], + dest: paths.dist + 'lib/font-awesome' + }, + { + src: paths.npmDir + 'jquery/dist/jquery.min.js', + dest: paths.dist + 'lib/jquery' + }, + { + src: paths.npmDir + 'angular/angular.min.js', + dest: paths.dist + 'lib/angular' + }, + { + src: [ + paths.webroot + '**/app/**/*.html', + paths.webroot + '**/images/**/*', + paths.webroot + 'index.html', + paths.webroot + 'favicon.ico' + ], + dest: paths.dist + } + ]; + + var tasks = moves.map(function (move) { + return gulp.src(move.src).pipe(gulp.dest(move.dest)); + }); + + return merge(tasks); +}); + +gulp.task('dist:css', function () { + return gulp + .src([ + paths.cssDir + '**/*.css', + '!' + paths.cssDir + '**/*.min.css' + ]) + .pipe(preprocess({ context: settings })) + .pipe(cssmin()) + .pipe(rename({ suffix: '.min' })) + .pipe(gulp.dest(paths.dist + 'css')); +}); + +gulp.task('dist:js:app', function () { + var mainStream = gulp + .src([ + paths.webroot + 'app/app.js', + '!' + paths.webroot + 'app/settings.js', + paths.webroot + 'app/**/*Module.js', + paths.webroot + 'app/**/*.js' + ]); + + merge(mainStream, config()) + .pipe(preprocess({ context: settings })) + .pipe(concat(paths.dist + '/js/app.min.js')) + .pipe(ngAnnotate()) + .pipe(uglify()) + .pipe(gulp.dest('.')); +}); + +gulp.task('dist:js:lib', function () { + return gulp + .src([ + paths.libDir + 'sjcl/sjcl.js', + paths.libDir + 'sjcl/*.js', + paths.libDir + '**/*.js', + '!' + paths.libDir + '**/*.min.js', + '!' + paths.libDir + 'angular/**/*', + '!' + paths.libDir + 'bootstrap/**/*', + '!' + paths.libDir + 'jquery/**/*' + ]) + .pipe(concat(paths.dist + '/js/lib.min.js')) + .pipe(uglify()) + .pipe(gulp.dest('.')); +}); + +gulp.task('dist:preprocess', function () { + return gulp + .src([ + paths.dist + '/**/*.html' + ], { base: '.' }) + .pipe(preprocess({ context: settings })) + .pipe(gulp.dest('.')); +}); + +gulp.task('dist', ['build'], function (cb) { + return runSequence( + 'dist:clean', + ['dist:move', 'dist:css', 'dist:js:app', 'dist:js:lib'], + 'dist:preprocess', + cb); +}); + +gulp.task('deploy', ['dist'], function () { + return gulp.src(paths.dist + '**/*') + .pipe(ghPages({ cacheDir: paths.dist + '.publish' })); +}); diff --git a/src/Vault/less/theme.less b/src/Vault/less/theme.less new file mode 100644 index 00000000..7b907ce6 --- /dev/null +++ b/src/Vault/less/theme.less @@ -0,0 +1,47 @@ +@import url(https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700,300italic,400italic,600italic); +@import "../node_modules/toastr/toastr.less"; + +/* Start AdminLTE */ + +//Bootstrap Variables & Mixins +//The core bootstrap code have not been modified. These files +//are included only for reference. +@import (reference) "../node_modules/admin-lte/build/bootstrap-less/mixins.less"; +@import (reference) "../node_modules/admin-lte/build/bootstrap-less/variables.less"; +//MISC +//---- +@import "../node_modules/admin-lte/build/less/core.less"; +@import "../node_modules/admin-lte/build/less/variables.less"; +@import "../node_modules/admin-lte/build/less/mixins.less"; +//COMPONENTS +//----------- +@import "../node_modules/admin-lte/build/less/header.less"; +@import "../node_modules/admin-lte/build/less/sidebar.less"; +@import "../node_modules/admin-lte/build/less/sidebar-mini.less"; +@import "../node_modules/admin-lte/build/less/control-sidebar.less"; +@import "../node_modules/admin-lte/build/less/dropdown.less"; +@import "../node_modules/admin-lte/build/less/forms.less"; +@import "../node_modules/admin-lte/build/less/progress-bars.less"; +@import "../node_modules/admin-lte/build/less/small-box.less"; +@import "../node_modules/admin-lte/build/less/boxes.less"; +@import "../node_modules/admin-lte/build/less/info-box.less"; +@import "../node_modules/admin-lte/build/less/timeline.less"; +@import "../node_modules/admin-lte/build/less/buttons.less"; +@import "../node_modules/admin-lte/build/less/callout.less"; +@import "../node_modules/admin-lte/build/less/alerts.less"; +@import "../node_modules/admin-lte/build/less/navs.less"; +@import "../node_modules/admin-lte/build/less/table.less"; +@import "../node_modules/admin-lte/build/less/labels.less"; +@import "../node_modules/admin-lte/build/less/modal.less"; +//PAGES +//------ +@import "../node_modules/admin-lte/build/less/login_and_register.less"; +@import "../node_modules/admin-lte/build/less/404_500_errors.less"; +//Miscellaneous +//------------- +@import "../node_modules/admin-lte/build/less/miscellaneous.less"; +@import "../node_modules/admin-lte/build/less/print.less"; + +/* End AdminLTE */ + +@import "../node_modules/admin-lte/build/less/skins/skin-blue.less"; diff --git a/src/Vault/less/vault.less b/src/Vault/less/vault.less new file mode 100644 index 00000000..36bd289b --- /dev/null +++ b/src/Vault/less/vault.less @@ -0,0 +1,170 @@ +@import "theme.less"; + +/* Theme Adjustments */ + +@boxed-layout-bg-image-path: "../images/boxed-bg.png"; + +body { + background-color: @gray; + .img-retina(@boxed-layout-bg-image-path, "../images/boxed-bg-2x.png", auto, auto); +} + +body, +.main-header .logo, +h1, h2, h3, h4, h5, h6, +.h1, .h2, .h3, .h4, .h5, .h6 { + font-family: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; +} + +.box-body > .table-responsive { + > .table { + margin-bottom: 0; + } + + @media screen and (max-width: @screen-xs-max) { + border: none; + margin-bottom: 0; + } +} + +.sidebar-form .form-group { + margin-bottom: 0; + + input[type="text"], .form-control-feedback { + color: #999; + } +} + +form div.validation-errors ul { + margin-bottom: 0; + padding-left: 20px; + + li { + margin-left: 0; + } +} + +.login-page, +.register-page { + background-color: @gray; + background-repeat: repeat; + background-attachment: fixed; + .img-retina(@boxed-layout-bg-image-path, "../images/boxed-bg-2x.png", auto, auto); +} + +.login-box-body, +.register-box-body { + .boxShadow(0 0 8px rgba(0, 0, 0, 0.5)); +} + +.login-box, .register-box { + .checkbox { + margin-top: 0; + } + + ul { + margin-bottom: 0; + padding-left: 20px; + } +} + +.password-options { + float: right; + + i { + margin: 0 5px; + cursor: pointer; + } +} + +/* Buttons */ + +.btn-table { + padding: 1px 5px; + line-height: 1; +} + +.btn-box-tool { + font-size: 14px; +} + +form .btn .loading-icon { + margin-right: 8px; +} + +/* Modals */ + +.modal-footer { + text-align: left; +} + +/* Toastr */ + +#toast-container { + position: absolute; + + &.toast-top-right { + top: 65px; + right: 15px; + + @media (max-width: @screen-xs-max) { + top: initial; + bottom: 0; + right: 0; + width: 100%; + } + } + + > .toast { + background-image: none !important; + .border-radius(0); + .boxShadow(0 0 8px rgba(0, 0, 0, 0.5)); + + @media (max-width: @screen-xs-max) { + width: 100%; + } + + &.toast-danger, &.toast-error { + &:extend(.bg-red); + + &:before { + content: "\f0e7"; + } + } + + &.toast-warning { + &:extend(.bg-yellow); + + &:before { + content: "\f071"; + } + } + + &.toast-info { + &:extend(.bg-aqua); + + &:before { + content: "\f005"; + } + } + + &.toast-success { + &:extend(.bg-green); + + &:before { + content: "\f00C"; + } + } + + &:before { + position: fixed; + font-family: FontAwesome; + font-size: 24px; + line-height: 24px; + float: left; + color: #ffffff; + padding-right: 0.5em; + margin: auto 0.5em auto -1.5em; + } + } +} diff --git a/src/Vault/package.json b/src/Vault/package.json new file mode 100644 index 00000000..695934de --- /dev/null +++ b/src/Vault/package.json @@ -0,0 +1,43 @@ +{ + "name": "bitwarden", + "version": "0.0.1", + "devDependencies": { + "connect": "^3.4.0", + "lodash": "3.10.1", + "gulp": "3.9.0", + "gulp-concat": "2.6.0", + "gulp-cssmin": "0.1.7", + "gulp-less": "3.0.3", + "gulp-rename": "1.2.2", + "gulp-uglify": "1.4.0", + "gulp-gh-pages": "0.5.4", + "gulp-preprocess": "1.2.0", + "gulp-ng-annotate": "1.1.0", + "gulp-ng-config": "1.2.1", + "jshint": "2.9.1-rc1", + "gulp-jshint": "2.0.0", + "rimraf": "2.4.3", + "run-sequence": "1.1.3", + "merge-stream": "1.0.0", + "jquery": "2.1.4", + "font-awesome": "4.4.0", + "bootstrap": "3.3.5", + "sjcl": "1.0.3", + "angular": "1.4.7", + "angular-resource": "1.4.7", + "angular-bootstrap-npm": "0.14.3", + "angular-ui-router": "0.2.15", + "angular-jwt": "0.0.9", + "angular-cookies": "1.4.7", + "admin-lte": "2.3.2", + "angular-md5": "0.1.8", + "angular-toastr": "1.5.0", + "angular-bootstrap-show-errors": "2.3.0", + "angular-messages": "1.4.7", + "ngstorage": "0.3.10", + "papaparse": "4.1.2", + "toastr": "2.1.2", + "clipboard": "1.5.5", + "ngclipboard": "1.0.0" + } +} diff --git a/src/Vault/project.json b/src/Vault/project.json new file mode 100644 index 00000000..26ec0c3b --- /dev/null +++ b/src/Vault/project.json @@ -0,0 +1,27 @@ +{ + "version": "0.0.1", + "environment": "Development", + + "dependencies": { + "Microsoft.AspNet.IISPlatformHandler": "1.0.0-rc1-final", + "Microsoft.AspNet.Server.Kestrel": "1.0.0-rc1-final", + "Microsoft.AspNet.StaticFiles": "1.0.0-rc1-final" + }, + + "commands": { + "web": "Microsoft.AspNet.Server.Kestrel" + }, + + "frameworks": { + "dnx451": { } + }, + + "exclude": [ + "wwwroot", + "node_modules" + ], + "publishExclude": [ + "**.user", + "**.vspscc" + ] +} diff --git a/src/Vault/settings.Development.json b/src/Vault/settings.Development.json new file mode 100644 index 00000000..d2bc61c9 --- /dev/null +++ b/src/Vault/settings.Development.json @@ -0,0 +1,5 @@ +{ + "appSettings": { + "apiUri": "http://localhost:4000" + } +} diff --git a/src/Vault/settings.Production.json b/src/Vault/settings.Production.json new file mode 100644 index 00000000..3be6a9c8 --- /dev/null +++ b/src/Vault/settings.Production.json @@ -0,0 +1,5 @@ +{ + "appSettings": { + "apiUri": "https://api.bitwarden.com" + } +} diff --git a/src/Vault/settings.Staging.json b/src/Vault/settings.Staging.json new file mode 100644 index 00000000..3be6a9c8 --- /dev/null +++ b/src/Vault/settings.Staging.json @@ -0,0 +1,5 @@ +{ + "appSettings": { + "apiUri": "https://api.bitwarden.com" + } +} diff --git a/src/Vault/settings.json b/src/Vault/settings.json new file mode 100644 index 00000000..2e50bde1 --- /dev/null +++ b/src/Vault/settings.json @@ -0,0 +1,5 @@ +{ + "appSettings": { + "rememberdEmailCookieName": "bit.rememberedEmail" + } +} diff --git a/src/Vault/wwwroot/_references.js b/src/Vault/wwwroot/_references.js new file mode 100644 index 00000000..725d3ce1 --- /dev/null +++ b/src/Vault/wwwroot/_references.js @@ -0,0 +1,48 @@ +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// diff --git a/src/Vault/wwwroot/app/accounts/accountsLoginController.js b/src/Vault/wwwroot/app/accounts/accountsLoginController.js new file mode 100644 index 00000000..01a1883f --- /dev/null +++ b/src/Vault/wwwroot/app/accounts/accountsLoginController.js @@ -0,0 +1,48 @@ +angular + .module('bit.accounts') + + .controller('accountsLoginController', function ($scope, $rootScope, $cookies, apiService, cryptoService, authService, $state, appSettings) { + var rememberedEmail = $cookies.get(appSettings.rememberdEmailCookieName); + if (rememberedEmail) { + $scope.model = { + email: rememberedEmail, + rememberEmail: true + }; + } + + $scope.login = function (model) { + $scope.loginPromise = authService.logIn(model.email, model.masterPassword); + + $scope.loginPromise.then(function () { + if (model.rememberEmail) { + var cookieExpiration = new Date(); + cookieExpiration.setFullYear(cookieExpiration.getFullYear() + 10); + + $cookies.put( + appSettings.rememberdEmailCookieName, + model.email, + { expires: cookieExpiration }); + } + else { + $cookies.remove(appSettings.rememberdEmailCookieName); + } + + var profile = authService.getUserProfile(); + if (profile.twoFactor) { + $state.go('frontend.login.twoFactor'); + } + else { + $state.go('backend.vault'); + } + }); + }; + + $scope.twoFactor = function (model) { + // Only supporting Authenticator provider for now + $scope.twoFactorPromise = authService.logInTwoFactor(model.code, "Authenticator"); + + $scope.twoFactorPromise.then(function () { + $state.go('backend.vault'); + }); + }; + }); diff --git a/src/Vault/wwwroot/app/accounts/accountsLogoutController.js b/src/Vault/wwwroot/app/accounts/accountsLogoutController.js new file mode 100644 index 00000000..ff513bd4 --- /dev/null +++ b/src/Vault/wwwroot/app/accounts/accountsLogoutController.js @@ -0,0 +1,7 @@ +angular + .module('bit.accounts') + + .controller('accountsLogoutController', function ($scope, authService, $state) { + authService.logOut(); + $state.go('frontend.login.info'); + }); diff --git a/src/Vault/wwwroot/app/accounts/accountsModule.js b/src/Vault/wwwroot/app/accounts/accountsModule.js new file mode 100644 index 00000000..dfa7f48b --- /dev/null +++ b/src/Vault/wwwroot/app/accounts/accountsModule.js @@ -0,0 +1,2 @@ +angular + .module('bit.accounts', ['ui.bootstrap', 'ngCookies']); diff --git a/src/Vault/wwwroot/app/accounts/accountsPasswordHintController.js b/src/Vault/wwwroot/app/accounts/accountsPasswordHintController.js new file mode 100644 index 00000000..45fe8fce --- /dev/null +++ b/src/Vault/wwwroot/app/accounts/accountsPasswordHintController.js @@ -0,0 +1,12 @@ +angular + .module('bit.accounts') + + .controller('accountsPasswordHintController', function ($scope, $rootScope, apiService) { + $scope.success = false; + + $scope.submit = function (model) { + $scope.submitPromise = apiService.accounts.postPasswordHint({ email: model.email }, function () { + $scope.success = true; + }).$promise; + }; + }); diff --git a/src/Vault/wwwroot/app/accounts/accountsRegisterController.js b/src/Vault/wwwroot/app/accounts/accountsRegisterController.js new file mode 100644 index 00000000..14563434 --- /dev/null +++ b/src/Vault/wwwroot/app/accounts/accountsRegisterController.js @@ -0,0 +1,13 @@ +angular + .module('bit.accounts') + + .controller('accountsRegisterController', function ($scope, $rootScope, apiService) { + $scope.success = false; + + $scope.registerPromise = null; + $scope.register = function (model) { + $scope.registerPromise = apiService.accounts.registerToken({ email: model.email }, function () { + $scope.success = true; + }).$promise; + }; + }); diff --git a/src/Vault/wwwroot/app/accounts/accountsRegisterFinalizeController.js b/src/Vault/wwwroot/app/accounts/accountsRegisterFinalizeController.js new file mode 100644 index 00000000..d0484d74 --- /dev/null +++ b/src/Vault/wwwroot/app/accounts/accountsRegisterFinalizeController.js @@ -0,0 +1,48 @@ +angular + .module('bit.accounts') + + .controller('accountsRegisterFinalizeController', function ($scope, $rootScope, $location, $state, apiService, cryptoService, validationService) { + var params = $location.search(); + + if (!params.token || !params.email) { + $state.go('frontend.login.info'); + return; + } + + $scope.success = false; + $scope.model = { + email: params.email, + token: params.token + }; + + $scope.info = function () { + $scope.model.confirmMasterPassword = null; + $state.go('frontend.registerFinalize.confirm'); + }; + + $scope.confirmPromise = null; + $scope.confirm = function (form) { + if ($scope.model.masterPassword != $scope.model.confirmMasterPassword) { + validationService.addError(form, 'ConfirmMasterPassword', 'Master password confirmation does not match.', true); + return; + } + + var key = cryptoService.makeKey($scope.model.masterPassword, $scope.model.email); + var request = { + token: $scope.model.token, + name: $scope.model.name, + email: $scope.model.email, + masterPasswordHash: cryptoService.hashPassword($scope.model.masterPassword, key), + masterPasswordHint: $scope.model.masterPasswordHint + }; + + $scope.confirmPromise = apiService.accounts.register(request, function () { + $scope.success = true; + }).$promise; + }; + + $scope.loadInfo = function () { + $scope.model.masterPassword = null; + window.history.back(); + }; + }); diff --git a/src/Vault/wwwroot/app/accounts/views/accountsLogin.html b/src/Vault/wwwroot/app/accounts/views/accountsLogin.html new file mode 100644 index 00000000..5775b44a --- /dev/null +++ b/src/Vault/wwwroot/app/accounts/views/accountsLogin.html @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/src/Vault/wwwroot/app/accounts/views/accountsLoginInfo.html b/src/Vault/wwwroot/app/accounts/views/accountsLoginInfo.html new file mode 100644 index 00000000..7bf478aa --- /dev/null +++ b/src/Vault/wwwroot/app/accounts/views/accountsLoginInfo.html @@ -0,0 +1,40 @@ + +
+
+

Errors have occured

+
    +
  • {{e}}
  • +
+
+
+ + + +
+
+ + + +
+
+
+
+ +
+
+
+ +
+
+
+ +
\ No newline at end of file diff --git a/src/Vault/wwwroot/app/accounts/views/accountsLoginTwoFactor.html b/src/Vault/wwwroot/app/accounts/views/accountsLoginTwoFactor.html new file mode 100644 index 00000000..db7fed6e --- /dev/null +++ b/src/Vault/wwwroot/app/accounts/views/accountsLoginTwoFactor.html @@ -0,0 +1,22 @@ + +
+
+

Errors have occured

+
    +
  • {{e}}
  • +
+
+
+ + + +
+
+
+ +
+
+
\ No newline at end of file diff --git a/src/Vault/wwwroot/app/accounts/views/accountsPasswordHint.html b/src/Vault/wwwroot/app/accounts/views/accountsPasswordHint.html new file mode 100644 index 00000000..d4f7f05d --- /dev/null +++ b/src/Vault/wwwroot/app/accounts/views/accountsPasswordHint.html @@ -0,0 +1,37 @@ + diff --git a/src/Vault/wwwroot/app/accounts/views/accountsRegister.html b/src/Vault/wwwroot/app/accounts/views/accountsRegister.html new file mode 100644 index 00000000..f4091e3a --- /dev/null +++ b/src/Vault/wwwroot/app/accounts/views/accountsRegister.html @@ -0,0 +1,37 @@ +
+ +
+ +
+
+

Almost done!

Check your email ({{model.email}}) to complete your registration. +
+ Ready to log in? +
+
+
+

Errors have occured

+
    +
  • {{e}}
  • +
+
+
+ + + +
+
+ +
+ +
+
+
+
+
\ No newline at end of file diff --git a/src/Vault/wwwroot/app/accounts/views/accountsRegisterFinalize.html b/src/Vault/wwwroot/app/accounts/views/accountsRegisterFinalize.html new file mode 100644 index 00000000..dd5b4156 --- /dev/null +++ b/src/Vault/wwwroot/app/accounts/views/accountsRegisterFinalize.html @@ -0,0 +1,7 @@ +
+ +
+
+
\ No newline at end of file diff --git a/src/Vault/wwwroot/app/accounts/views/accountsRegisterFinalizeConfirm.html b/src/Vault/wwwroot/app/accounts/views/accountsRegisterFinalizeConfirm.html new file mode 100644 index 00000000..b7bbffca --- /dev/null +++ b/src/Vault/wwwroot/app/accounts/views/accountsRegisterFinalizeConfirm.html @@ -0,0 +1,35 @@ + +
+
+

You're Registered!

+

You may now log in to your new account.

+
+ Ready to log in? +
+
+
+

Errors have occured

+
    +
  • {{e}}
  • +
+
+
+ + + +

It is very important that you do not forget your master password. There is no way to recover the password in the event that you forget it.

+
+
+
+ +
+ +
+
+
\ No newline at end of file diff --git a/src/Vault/wwwroot/app/accounts/views/accountsRegisterFinalizeInfo.html b/src/Vault/wwwroot/app/accounts/views/accountsRegisterFinalizeInfo.html new file mode 100644 index 00000000..abe8cbd7 --- /dev/null +++ b/src/Vault/wwwroot/app/accounts/views/accountsRegisterFinalizeInfo.html @@ -0,0 +1,35 @@ + +
+
+ + + +
+
+ + + +

What should we call you?

+
+
+ + + +

The master password is the password you use to access your vault.

+
+
+ + + +

A master password hint can help you remember your password if you forget it.

+
+
+
+ +
+ +
+
+
diff --git a/src/Vault/wwwroot/app/apiInterceptor.js b/src/Vault/wwwroot/app/apiInterceptor.js new file mode 100644 index 00000000..5040b83e --- /dev/null +++ b/src/Vault/wwwroot/app/apiInterceptor.js @@ -0,0 +1,29 @@ +angular + .module('bit') + + .factory('apiInterceptor', function ($injector, $q, toastr) { + return { + request: function (config) { + return config; + }, + response: function (response) { + if (response.status === 401 || response.status == 403) { + $injector.get('authService').logOut(); + $injector.get('$state').go('frontend.login.info').then(function () { + toastr.warning('Your login session has expired.', 'Logged out'); + }); + } + + return response || $q.when(response); + }, + responseError: function (rejection) { + if (rejection.status === 401 || rejection.status == 403) { + $injector.get('authService').logOut(); + $injector.get('$state').go('frontend.login.info').then(function () { + toastr.warning('Your login session has expired.', 'Logged out'); + }); + } + return $q.reject(rejection); + } + }; + }); \ No newline at end of file diff --git a/src/Vault/wwwroot/app/app.js b/src/Vault/wwwroot/app/app.js new file mode 100644 index 00000000..b27f39d2 --- /dev/null +++ b/src/Vault/wwwroot/app/app.js @@ -0,0 +1,18 @@ +angular + .module('bit', [ + 'ui.router', + 'ngMessages', + 'angular-jwt', + 'angular-md5', + 'ui.bootstrap.showErrors', + 'toastr', + + 'bit.directives', + 'bit.services', + + 'bit.global', + 'bit.accounts', + 'bit.vault', + 'bit.settings', + 'bit.tools' + ]); diff --git a/src/Vault/wwwroot/app/config.js b/src/Vault/wwwroot/app/config.js new file mode 100644 index 00000000..acedfd38 --- /dev/null +++ b/src/Vault/wwwroot/app/config.js @@ -0,0 +1,157 @@ +angular + .module('bit') + + .config(function ($stateProvider, $urlRouterProvider, $httpProvider, jwtInterceptorProvider, $uibTooltipProvider, toastrConfig) { + jwtInterceptorProvider.tokenGetter = /*@ngInject*/ function (config, appSettings, tokenService) { + if (config.url.indexOf(appSettings.apiUri) === 0) { + return tokenService.getToken(); + } + }; + + angular.extend(toastrConfig, { + closeButton: true, + progressBar: true, + showMethod: 'slideDown', + target: '.toast-target' + }); + + $uibTooltipProvider.options({ + popupDelay: 600 + }); + + if (!$httpProvider.defaults.headers.get) { + $httpProvider.defaults.headers.get = {}; + } + + $httpProvider.defaults.headers.get['If-Modified-Since'] = 'Mon, 26 Jul 1997 05:00:00 GMT'; + $httpProvider.defaults.headers.get['Cache-Control'] = 'no-cache'; + $httpProvider.defaults.headers.get.Pragma = 'no-cache'; + + $httpProvider.interceptors.push('apiInterceptor'); + $httpProvider.interceptors.push('jwtInterceptor'); + + $urlRouterProvider.otherwise('/'); + + $stateProvider + // Backend + .state('backend', { + templateUrl: 'app/views/backendLayout.html', + abstract: true, + data: { + authorize: true + } + }) + .state('backend.vault', { + url: '^/', + templateUrl: 'app/vault/views/vault.html', + controller: 'vaultController', + data: { pageTitle: 'My Vault' } + }) + .state('backend.settings', { + url: '^/settings', + templateUrl: 'app/settings/views/settings.html', + controller: 'settingsController', + data: { pageTitle: 'Settings' } + }) + .state('backend.tools', { + url: '^/tools', + templateUrl: 'app/tools/views/tools.html', + controller: 'toolsController', + data: { pageTitle: 'Tools' } + }) + + // Frontend + .state('frontend', { + templateUrl: 'app/views/frontendLayout.html', + abstract: true, + data: { + authorize: false + } + }) + .state('frontend.login', { + templateUrl: 'app/accounts/views/accountsLogin.html', + controller: 'accountsLoginController', + data: { + bodyClass: 'login-page' + } + }) + .state('frontend.login.info', { + url: '^/login', + templateUrl: 'app/accounts/views/accountsLoginInfo.html', + data: { + pageTitle: 'Log In' + } + }) + .state('frontend.login.twoFactor', { + url: '^/login/two-factor', + templateUrl: 'app/accounts/views/accountsLoginTwoFactor.html', + data: { + pageTitle: 'Log In (Two Factor)', + authorizeTwoFactor: true + } + }) + .state('frontend.logout', { + url: '^/logout', + controller: 'accountsLogoutController', + data: { + authorize: true + } + }) + .state('frontend.passwordHint', { + url: '^/password-hint', + templateUrl: 'app/accounts/views/accountsPasswordHint.html', + controller: 'accountsPasswordHintController', + data: { + pageTitle: 'Master Password Hint', + bodyClass: 'login-page' + } + }) + .state('frontend.register', { + url: '^/register', + templateUrl: 'app/accounts/views/accountsRegister.html', + controller: 'accountsRegisterController', + data: { + pageTitle: 'Register', + bodyClass: 'register-page' + } + }) + .state('frontend.registerFinalize', { + controller: 'accountsRegisterFinalizeController', + templateUrl: 'app/accounts/views/accountsRegisterFinalize.html', + data: { + bodyClass: 'register-page' + } + }) + .state('frontend.registerFinalize.info', { + url: '^/register/finalize', + templateUrl: 'app/accounts/views/accountsRegisterFinalizeInfo.html', + data: { + pageTitle: 'Finalize Registration' + } + }) + .state('frontend.registerFinalize.confirm', { + url: '^/register/finalize/confirm', + templateUrl: 'app/accounts/views/accountsRegisterFinalizeConfirm.html', + data: { + pageTitle: 'Finalize Registration (Confirm)' + } + }); + }) + .run(function ($rootScope, authService, jwtHelper, tokenService, $state) { + $rootScope.$on('$stateChangeStart', function (event, toState, toParams) { + if (!toState.data || !toState.data.authorize) { + if (authService.isAuthenticated() && !jwtHelper.isTokenExpired(tokenService.getToken())) { + event.preventDefault(); + $state.go('backend.vault'); + } + + return; + } + + if (!authService.isAuthenticated() || jwtHelper.isTokenExpired(tokenService.getToken())) { + event.preventDefault(); + authService.logOut(); + $state.go('frontend.login.info'); + } + }); + }); \ No newline at end of file diff --git a/src/Vault/wwwroot/app/directives/apiFieldDirective.js b/src/Vault/wwwroot/app/directives/apiFieldDirective.js new file mode 100644 index 00000000..a053712a --- /dev/null +++ b/src/Vault/wwwroot/app/directives/apiFieldDirective.js @@ -0,0 +1,30 @@ +angular + .module('bit.directives') + + .directive('apiField', function () { + var linkFn = function (scope, element, attrs, ngModel) { + ngModel.$registerApiError = registerApiError; + ngModel.$validators.apiValidate = apiValidator; + + function apiValidator() { + ngModel.$setValidity('api', true); + return true; + } + + function registerApiError() { + ngModel.$setValidity('api', false); + } + }; + + return { + require: 'ngModel', + restrict: 'A', + compile: function (elem, attrs) { + if (!attrs.name || attrs.name === '') { + throw 'api-field element does not have a valid name attribute'; + } + + return linkFn; + } + }; + }); \ No newline at end of file diff --git a/src/Vault/wwwroot/app/directives/apiFormDirective.js b/src/Vault/wwwroot/app/directives/apiFormDirective.js new file mode 100644 index 00000000..f240ab53 --- /dev/null +++ b/src/Vault/wwwroot/app/directives/apiFormDirective.js @@ -0,0 +1,35 @@ +angular + .module('bit.directives') + + .directive('apiForm', function ($rootScope, validationService) { + return { + require: 'form', + restrict: 'A', + link: function (scope, element, attrs, formCtrl) { + var watchPromise = attrs.apiForm || null; + if (watchPromise !== void 0) { + scope.$watch(watchPromise, formSubmitted.bind(null, formCtrl, scope)); + } + } + }; + + function formSubmitted(form, scope, promise) { + if (!promise || !promise.then) { + return; + } + + // reset errors + form.$errors = null; + + // start loading + form.$loading = true; + + promise.then(function success(response) { + form.$loading = false; + }, function failure(reason) { + form.$loading = false; + validationService.addErrors(form, reason); + scope.$broadcast('show-errors-check-validity'); + }); + } + }); \ No newline at end of file diff --git a/src/Vault/wwwroot/app/directives/directivesModule.js b/src/Vault/wwwroot/app/directives/directivesModule.js new file mode 100644 index 00000000..ad4865f1 --- /dev/null +++ b/src/Vault/wwwroot/app/directives/directivesModule.js @@ -0,0 +1,2 @@ +angular + .module('bit.directives', []); diff --git a/src/Vault/wwwroot/app/directives/masterPasswordDirective.js b/src/Vault/wwwroot/app/directives/masterPasswordDirective.js new file mode 100644 index 00000000..7c5eb8fe --- /dev/null +++ b/src/Vault/wwwroot/app/directives/masterPasswordDirective.js @@ -0,0 +1,40 @@ +angular + .module('bit.directives') + + .directive('masterPassword', function (cryptoService, authService) { + return { + require: 'ngModel', + restrict: 'A', + link: function (scope, elem, attr, ngModel) { + var profile = authService.getUserProfile(); + if (!profile) { + return; + } + + // For DOM -> model validation + ngModel.$parsers.unshift(function (value) { + if (!value) { + return undefined; + } + + var key = cryptoService.makeKey(value, profile.email, true); + var valid = key == cryptoService.getKey(true); + ngModel.$setValidity('masterPassword', valid); + return valid ? value : undefined; + }); + + // For model -> DOM validation + ngModel.$formatters.unshift(function (value) { + if (!value) { + return undefined; + } + + var key = cryptoService.makeKey(value, profile.email, true); + var valid = key == cryptoService.getKey(true); + + ngModel.$setValidity('masterPassword', valid); + return value; + }); + } + }; + }); \ No newline at end of file diff --git a/src/Vault/wwwroot/app/directives/pageTitleDirective.js b/src/Vault/wwwroot/app/directives/pageTitleDirective.js new file mode 100644 index 00000000..8385b3f8 --- /dev/null +++ b/src/Vault/wwwroot/app/directives/pageTitleDirective.js @@ -0,0 +1,22 @@ +angular + .module('bit.directives') + + .directive('pageTitle', function ($rootScope, $timeout, appSettings) { + return { + link: function (scope, element) { + var listener = function (event, toState, toParams, fromState, fromParams) { + // Default title + var title = 'bitwarden Password Manager'; + if (toState.data && toState.data.pageTitle) { + title = toState.data.pageTitle + ' - bitwarden Password Manager'; + } + + $timeout(function () { + element.text(title); + }); + }; + + $rootScope.$on('$stateChangeStart', listener); + } + }; + }); \ No newline at end of file diff --git a/src/Vault/wwwroot/app/directives/passwordMeterDirective.js b/src/Vault/wwwroot/app/directives/passwordMeterDirective.js new file mode 100644 index 00000000..4c9b1fcb --- /dev/null +++ b/src/Vault/wwwroot/app/directives/passwordMeterDirective.js @@ -0,0 +1,73 @@ +angular + .module('bit.directives') + + .directive('passwordMeter', function () { + return { + template: '
{{value}}%
', + restrict: 'A', + scope: { + password: '=passwordMeter', + username: '=passwordMeterUsername', + value: '=passwordMeterStrength', + outerClass: '@?' + }, + link: function (scope) { + var measureStrength = function (username, password) { + if (!password || password == username) { + return 0; + } + + var strength = password.length; + + if (username && username !== '') { + if (username.indexOf(password) != -1) strength -= 15; + if (password.indexOf(username) != -1) strength -= username.length; + } + + if (password.length > 0 && password.length <= 4) strength += password.length; + else if (password.length >= 5 && password.length <= 7) strength += 6; + else if (password.length >= 8 && password.length <= 15) strength += 12; + else if (password.length >= 16) strength += 18; + + if (password.match(/[a-z]/)) strength += 1; + if (password.match(/[A-Z]/)) strength += 5; + if (password.match(/\d/)) strength += 5; + if (password.match(/.*\d.*\d.*\d/)) strength += 5; + if (password.match(/[!,@,#,$,%,^,&,*,?,_,~]/)) strength += 5; + if (password.match(/.*[!,@,#,$,%,^,&,*,?,_,~].*[!,@,#,$,%,^,&,*,?,_,~]/)) strength += 5; + if (password.match(/(?=.*[a-z])(?=.*[A-Z])/)) strength += 2; + if (password.match(/(?=.*\d)(?=.*[a-z])(?=.*[A-Z])/)) strength += 2; + if (password.match(/(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[!,@,#,$,%,^,&,*,?,_,~])/)) strength += 2; + + strength = Math.round(strength * 2); + return Math.max(0, Math.min(100, strength)); + }; + + var getClass = function (strength) { + switch (Math.round(strength / 33)) { + case 0: + case 1: + return 'danger'; + + case 2: + return 'warning'; + case 3: + return 'success'; + } + }; + + var updateMeter = function (scope) { + scope.value = measureStrength(scope.username, scope.password); + scope.valueClass = getClass(scope.value); + }; + + scope.$watch('password', function () { + updateMeter(scope); + }); + + scope.$watch('username', function () { + updateMeter(scope); + }); + }, + }; + }); diff --git a/src/Vault/wwwroot/app/directives/passwordViewerDirective.js b/src/Vault/wwwroot/app/directives/passwordViewerDirective.js new file mode 100644 index 00000000..5772b08d --- /dev/null +++ b/src/Vault/wwwroot/app/directives/passwordViewerDirective.js @@ -0,0 +1,27 @@ +angular + .module('bit.directives') + + .directive('passwordViewer', function () { + return { + restrict: 'A', + link: function (scope, element, attr) { + var passwordViewer = attr.passwordViewer; + if (!passwordViewer) { + return; + } + + element.onclick = function (event) { }; + element.on('click', function (event) { + var passwordElement = $(passwordViewer); + if (passwordElement && passwordElement.attr('type') == 'password') { + element.removeClass('fa-eye').addClass('fa-eye-slash'); + passwordElement.attr('type', 'text'); + } + else if (passwordElement && passwordElement.attr('type') == 'text') { + element.removeClass('fa-eye-slash').addClass('fa-eye'); + passwordElement.attr('type', 'password'); + } + }); + } + }; + }); diff --git a/src/Vault/wwwroot/app/global/globalModule.js b/src/Vault/wwwroot/app/global/globalModule.js new file mode 100644 index 00000000..9af6c4b9 --- /dev/null +++ b/src/Vault/wwwroot/app/global/globalModule.js @@ -0,0 +1,2 @@ +angular + .module('bit.global', []); diff --git a/src/Vault/wwwroot/app/global/mainController.js b/src/Vault/wwwroot/app/global/mainController.js new file mode 100644 index 00000000..a9aa96ff --- /dev/null +++ b/src/Vault/wwwroot/app/global/mainController.js @@ -0,0 +1,78 @@ +angular + .module('bit.global') + + .controller('mainController', function ($scope, $state, authService, appSettings, toastr) { + var vm = this; + vm.bodyClass = ''; + vm.userProfile = null; + vm.searchVaultText = null; + vm.version = appSettings.version; + + $scope.currentYear = new Date().getFullYear(); + + $scope.$on('$viewContentLoaded', function () { + if ($.AdminLTE) { + if ($.AdminLTE.layout) { + $.AdminLTE.layout.fix(); + $.AdminLTE.layout.fixSidebar(); + } + + if ($.AdminLTE.pushMenu) { + $.AdminLTE.pushMenu.expandOnHover(); + } + } + }); + + $scope.$on('$stateChangeSuccess', function (event, toState, toParams, fromState, fromParams) { + vm.searchVaultText = null; + vm.userProfile = authService.getUserProfile(); + + if (toState.data.bodyClass) { + vm.bodyClass = toState.data.bodyClass; + return; + } + else { + vm.bodyClass = ''; + } + }); + + $scope.searchVault = function () { + $state.go('backend.vault'); + }; + + $scope.addSite = function () { + $scope.$broadcast('vaultAddSite'); + }; + + $scope.addFolder = function () { + $scope.$broadcast('vaultAddFolder'); + }; + + $scope.changeEmail = function () { + $scope.$broadcast('settingsChangeEmail'); + }; + + $scope.changePassword = function () { + $scope.$broadcast('settingsChangePassword'); + }; + + $scope.sessions = function () { + $scope.$broadcast('settingsSessions'); + }; + + $scope.twoFactor = function () { + $scope.$broadcast('settingsTwoFactor'); + }; + + $scope.import = function () { + $scope.$broadcast('toolsImport'); + }; + + $scope.export = function () { + $scope.$broadcast('toolsExport'); + }; + + $scope.audits = function () { + $scope.$broadcast('toolsAudits'); + }; + }); diff --git a/src/Vault/wwwroot/app/global/sideNavController.js b/src/Vault/wwwroot/app/global/sideNavController.js new file mode 100644 index 00000000..4d41c06c --- /dev/null +++ b/src/Vault/wwwroot/app/global/sideNavController.js @@ -0,0 +1,6 @@ +angular + .module('bit.global') + + .controller('sideNavController', function ($scope, $state) { + $scope.$state = $state; + }); diff --git a/src/Vault/wwwroot/app/global/topNavController.js b/src/Vault/wwwroot/app/global/topNavController.js new file mode 100644 index 00000000..2cdacba4 --- /dev/null +++ b/src/Vault/wwwroot/app/global/topNavController.js @@ -0,0 +1,6 @@ +angular + .module('bit.global') + + .controller('topNavController', function ($scope) { + + }); diff --git a/src/Vault/wwwroot/app/services/apiService.js b/src/Vault/wwwroot/app/services/apiService.js new file mode 100644 index 00000000..0e825e1a --- /dev/null +++ b/src/Vault/wwwroot/app/services/apiService.js @@ -0,0 +1,48 @@ +angular + .module('bit.services') + + .factory('apiService', function ($resource, tokenService, appSettings) { + var _service = {}, + _apiUri = appSettings.apiUri; + + _service.sites = $resource(_apiUri + '/sites/:id', {}, { + get: { method: 'GET', params: { id: '@id' } }, + list: { method: 'GET', params: {} }, + post: { method: 'POST', params: {} }, + put: { method: 'PUT', params: { id: '@id' } }, + del: { method: 'DELETE', params: { id: '@id' } } + }); + + _service.folders = $resource(_apiUri + '/folders/:id', {}, { + get: { method: 'GET', params: { id: '@id' } }, + list: { method: 'GET', params: {} }, + post: { method: 'POST', params: {} }, + put: { method: 'PUT', params: { id: '@id' } }, + del: { method: 'DELETE', params: { id: '@id' } } + }); + + _service.ciphers = $resource(_apiUri + '/ciphers/:id', {}, { + putMany: { url: _apiUri + '/ciphers/many', method: 'PUT', params: {} } + }); + + _service.accounts = $resource(_apiUri + '/accounts', {}, { + registerToken: { url: _apiUri + '/accounts/register-token', method: 'POST', params: {} }, + register: { url: _apiUri + '/accounts/register', method: 'POST', params: {} }, + emailToken: { url: _apiUri + '/accounts/email-token', method: 'POST', params: {} }, + email: { url: _apiUri + '/accounts/email', method: 'PUT', params: {} }, + putPassword: { url: _apiUri + '/accounts/password', method: 'PUT', params: {} }, + getProfile: { url: _apiUri + '/accounts/profile', method: 'GET', params: {} }, + putProfile: { url: _apiUri + '/accounts/profile', method: 'PUT', params: {} }, + getTwoFactor: { url: _apiUri + '/accounts/two-factor', method: 'GET', params: {} }, + putTwoFactor: { url: _apiUri + '/accounts/two-factor', method: 'PUT', params: {} }, + postPasswordHint: { url: _apiUri + '/accounts/password-hint', method: 'POST', params: {} }, + putSecurityStamp: { url: _apiUri + '/accounts/security-stamp', method: 'PUT', params: {} } + }); + + _service.auth = $resource(_apiUri + '/auth', {}, { + token: { url: _apiUri + '/auth/token', method: 'POST', params: {} }, + tokenTwoFactor: { url: _apiUri + '/auth/token/two-factor', method: 'POST', params: {} } + }); + + return _service; + }); diff --git a/src/Vault/wwwroot/app/services/authService.js b/src/Vault/wwwroot/app/services/authService.js new file mode 100644 index 00000000..d34391f3 --- /dev/null +++ b/src/Vault/wwwroot/app/services/authService.js @@ -0,0 +1,111 @@ +angular + .module('bit.services') + + .factory('authService', function (cryptoService, apiService, tokenService, $q, jwtHelper) { + var _service = {}, + _userProfile = null; + + _service.logIn = function (email, masterPassword) { + var key = cryptoService.makeKey(masterPassword, email); + + var request = { + email: email, + masterPasswordHash: cryptoService.hashPassword(masterPassword, key) + }; + + var deferred = $q.defer(); + apiService.auth.token(request, function (response) { + if (!response || !response.Token) { + return; + } + + tokenService.setToken(response.Token); + cryptoService.setKey(key); + _service.setUserProfile(response.Profile); + + deferred.resolve(response); + }, function (error) { + deferred.reject(error); + }); + + return deferred.promise; + }; + + _service.logInTwoFactor = function (code, provider) { + var request = { + code: code, + provider: provider + }; + + var deferred = $q.defer(); + apiService.auth.tokenTwoFactor(request, function (response) { + if (!response || !response.Token) { + return; + } + + tokenService.setToken(response.Token); + _service.setUserProfile(response.Profile); + + deferred.resolve(response); + }, function (error) { + deferred.reject(error); + }); + + return deferred.promise; + }; + + _service.logOut = function () { + tokenService.clearToken(); + cryptoService.clearKey(); + _userProfile = null; + }; + + _service.getUserProfile = function () { + if (!_userProfile) { + _service.setUserProfile(); + } + + return _userProfile; + }; + + _service.setUserProfile = function (profile) { + var token = tokenService.getToken(); + if (!token) { + return; + } + + var decodedToken = jwtHelper.decodeToken(token); + var twoFactor = decodedToken.authmethod == "TwoFactor"; + + _userProfile = { + id: decodedToken.nameid, + email: decodedToken.email, + twoFactor: twoFactor + }; + + if (!twoFactor && profile) { + loadProfile(profile); + } + else if (!twoFactor && !profile) { + apiService.accounts.getProfile({}, loadProfile); + } + }; + + function loadProfile(profile) { + _userProfile.extended = { + name: profile.Name, + twoFactorEnabled: profile.TwoFactorEnabled, + culture: profile.Culture + }; + } + + _service.isAuthenticated = function () { + return _service.getUserProfile() !== null && !_service.getUserProfile().twoFactor; + }; + + _service.isTwoFactorAuthenticated = function () { + return _service.getUserProfile() !== null && _service.getUserProfile().twoFactor; + }; + + return _service; + }); diff --git a/src/Vault/wwwroot/app/services/cipherService.js b/src/Vault/wwwroot/app/services/cipherService.js new file mode 100644 index 00000000..ffb98e1f --- /dev/null +++ b/src/Vault/wwwroot/app/services/cipherService.js @@ -0,0 +1,110 @@ +angular + .module('bit.services') + + .factory('cipherService', function (cryptoService, apiService) { + var _service = {}; + + _service.decryptSites = function (encryptedSites) { + if (!encryptedSites) throw "encryptedSites is undefined or null"; + + var unencryptedSites = []; + for (var i = 0; i < encryptedSites.length; i++) { + unencryptedSites.push(_service.decryptSite(encryptedSites[i])); + } + + return unencryptedSites; + }; + + _service.decryptSite = function (encryptedSite) { + if (!encryptedSite) throw "encryptedSite is undefined or null"; + + var site = { + id: encryptedSite.Id, + 'type': 1, + folderId: encryptedSite.FolderId, + name: cryptoService.decrypt(encryptedSite.Name), + uri: cryptoService.decrypt(encryptedSite.Uri), + username: cryptoService.decrypt(encryptedSite.Username), + password: cryptoService.decrypt(encryptedSite.Password), + notes: encryptedSite.Notes && encryptedSite.Notes !== '' ? cryptoService.decrypt(encryptedSite.Notes) : null + }; + + if (encryptedSite.Folder) { + site.folder = { + name: cryptoService.decrypt(encryptedSite.Folder.Name) + }; + } + + return site; + }; + + _service.decryptFolders = function (encryptedFolders) { + if (!encryptedFolders) throw "encryptedFolders is undefined or null"; + + var unencryptedFolders = []; + for (var i = 0; i < encryptedFolders.length; i++) { + unencryptedFolders.push(_service.decryptFolder(encryptedFolders[i])); + } + + return unencryptedFolders; + }; + + _service.decryptFolder = function (encryptedFolder) { + if (!encryptedFolder) throw "encryptedFolder is undefined or null"; + + return { + id: encryptedFolder.Id, + 'type': 0, + name: cryptoService.decrypt(encryptedFolder.Name) + }; + }; + + _service.encryptSites = function (unencryptedSites, key) { + if (!unencryptedSites) throw "unencryptedSites is undefined or null"; + + var encryptedSites = []; + for (var i = 0; i < unencryptedSites.length; i++) { + encryptedSites.push(_service.encryptSite(unencryptedSites[i], key)); + } + + return encryptedSites; + }; + + _service.encryptSite = function (unencryptedSite, key) { + if (!unencryptedSite) throw "unencryptedSite is undefined or null"; + + return { + id: unencryptedSite.id, + 'type': 1, + folderId: unencryptedSite.folderId === '' ? null : unencryptedSite.folderId, + uri: cryptoService.encrypt(unencryptedSite.uri, key), + name: cryptoService.encrypt(unencryptedSite.name, key), + username: cryptoService.encrypt(unencryptedSite.username, key), + password: cryptoService.encrypt(unencryptedSite.password, key), + notes: !unencryptedSite.notes || unencryptedSite.notes === '' ? null : cryptoService.encrypt(unencryptedSite.notes, key) + }; + }; + + _service.encryptFolders = function (unencryptedFolders, key) { + if (!unencryptedFolders) throw "unencryptedFolders is undefined or null"; + + var encryptedFolders = []; + for (var i = 0; i < unencryptedFolders.length; i++) { + encryptedFolders.push(_service.encryptFolder(unencryptedFolders[i], key)); + } + + return encryptedFolders; + }; + + _service.encryptFolder = function (unencryptedFolder, key) { + if (!unencryptedFolder) throw "unencryptedFolder is undefined or null"; + + return { + id: unencryptedFolder.id, + 'type': 0, + name: cryptoService.encrypt(unencryptedFolder.name, key) + }; + }; + + return _service; + }); diff --git a/src/Vault/wwwroot/app/services/cryptoService.js b/src/Vault/wwwroot/app/services/cryptoService.js new file mode 100644 index 00000000..c658ff8b --- /dev/null +++ b/src/Vault/wwwroot/app/services/cryptoService.js @@ -0,0 +1,114 @@ +angular + .module('bit.services') + + .factory('cryptoService', function ($sessionStorage) { + var _service = {}, + _key, + _b64Key, + _aes; + + sjcl.beware["CBC mode is dangerous because it doesn't protect message integrity."](); + + _service.setKey = function (key) { + _key = key; + $sessionStorage.key = sjcl.codec.base64.fromBits(key); + }; + + _service.getKey = function (b64) { + if (b64 && b64 === true && _b64Key) { + return _b64Key; + } + else if (!b64 && _key) { + return _key; + } + + if ($sessionStorage.key) { + _key = sjcl.codec.base64.toBits($sessionStorage.key); + } + + if (b64 && b64 === true) { + _b64Key = sjcl.codec.base64.fromBits(_key); + return _b64Key; + } + + return _key; + }; + + _service.clearKey = function () { + _key = _b64Key = _aes = null; + delete $sessionStorage.key; + }; + + _service.makeKey = function (password, salt, b64) { + var key = sjcl.misc.pbkdf2(password, salt, 5000, 256, null); + + if (b64 && b64 === true) { + return sjcl.codec.base64.fromBits(key); + } + + return key; + }; + + _service.hashPassword = function (password, key) { + if (!key) { + key = _service.getKey(); + } + + if (!password || !key) { + throw 'Invalid parameters.'; + } + + var hashBits = sjcl.misc.pbkdf2(key, password, 1, 256, null); + return sjcl.codec.base64.fromBits(hashBits); + }; + + _service.getAes = function () { + if (!_aes && _service.getKey()) { + _aes = new sjcl.cipher.aes(_service.getKey()); + } + + return _aes; + }; + + _service.encrypt = function (plaintextValue, key) { + if (!_service.getKey() && !key) { + throw 'Encryption key unavailable.'; + } + + if (!key) { + key = _service.getKey(); + } + + var response = {}; + var params = { + mode: "cbc", + iv: sjcl.random.randomWords(4, 0) + }; + + var ctJson = sjcl.encrypt(key, plaintextValue, params, response); + + var ct = ctJson.match(/"ct":"([^"]*)"/)[1]; + var iv = sjcl.codec.base64.fromBits(response.iv); + + return iv + "|" + ct; + }; + + _service.decrypt = function (encValue) { + if (!_service.getAes()) { + throw 'AES encryption unavailable.'; + } + + var encPieces = encValue.split('|'); + if (encPieces.length != 2) { + return ''; + } + + var ivBits = sjcl.codec.base64.toBits(encPieces[0]); + var ctBits = sjcl.codec.base64.toBits(encPieces[1]); + + var decBits = sjcl.mode.cbc.decrypt(_service.getAes(), ctBits, ivBits, null); + return sjcl.codec.utf8String.fromBits(decBits); + }; + + return _service; + }); diff --git a/src/Vault/wwwroot/app/services/passwordService.js b/src/Vault/wwwroot/app/services/passwordService.js new file mode 100644 index 00000000..4a67c3a1 --- /dev/null +++ b/src/Vault/wwwroot/app/services/passwordService.js @@ -0,0 +1,105 @@ +angular + .module('bit.services') + + .factory('passwordService', function () { + var _service = {}; + + _service.generatePassword = function (options) { + var defaults = { + length: 10, + ambiguous: false, + number: true, + minNumber: 1, + uppercase: true, + minUppercase: 1, + lowercase: true, + minLowercase: 1, + special: false, + minSpecial: 1 + }; + + // overload defaults with given options + var o = angular.extend({}, defaults, options); + + // sanitize + if (o.uppercase && o.minUppercase < 0) o.minUppercase = 1; + if (o.lowercase && o.minLowercase < 0) o.minLowercase = 1; + if (o.number && o.minNumber < 0) o.minNumber = 1; + if (o.special && o.minSpecial < 0) o.minSpecial = 1; + + if (!o.length || o.length < 1) o.length = 10; + var minLength = o.minUppercase + o.minLowercase + o.minNumber + o.minSpecial; + if (o.length < minLength) o.length = minLength; + + var positions = []; + if (o.lowercase && o.minLowercase > 0) { + for (var i = 0; i < o.minLowercase; i++) { + positions.push('l'); + } + } + if (o.uppercase && o.minUppercase > 0) { + for (var j = 0; j < o.minUppercase; j++) { + positions.push('u'); + } + } + if (o.number && o.minNumber > 0) { + for (var k = 0; k < o.minNumber; k++) { + positions.push('n'); + } + } + if (o.special && o.minSpecial > 0) { + for (var l = 0; l < o.minSpecial; l++) { + positions.push('s'); + } + } + while (positions.length < o.length) { + positions.push('a'); + } + + // shuffle + positions.sort(function () { + return randomInt(0, 1) * 2 - 1; + }); + + // build out the char sets + var allCharSet = ''; + + var lowercaseCharSet = 'abcdefghijkmnopqrstuvwxyz'; + if (o.ambiguous) lowercaseCharSet += 'l'; + if (o.lowercase) allCharSet += lowercaseCharSet; + + var uppercaseCharSet = 'ABCDEFGHIJKLMNPQRSTUVWXYZ'; + if (o.ambiguous) uppercaseCharSet += 'O'; + if (o.uppercase) allCharSet += uppercaseCharSet; + + var numberCharSet = '23456789'; + if (o.ambiguous) numberCharSet += '01'; + if (o.number) allCharSet += numberCharSet; + + var specialCharSet = '!@#$%^&*'; + if (o.special) allCharSet += specialCharSet; + + var password = ''; + for (var m = 0; m < o.length; m++) { + var positionChars; + switch (positions[m]) { + case 'l': positionChars = lowercaseCharSet; break; + case 'u': positionChars = uppercaseCharSet; break; + case 'n': positionChars = numberCharSet; break; + case 's': positionChars = specialCharSet; break; + case 'a': positionChars = allCharSet; break; + } + + var randomCharIndex = randomInt(0, positionChars.length - 1); + password += positionChars.charAt(randomCharIndex); + } + + return password; + }; + + function randomInt(min, max) { + return Math.floor(Math.random() * (max - min + 1)) + min; + } + + return _service; + }); diff --git a/src/Vault/wwwroot/app/services/servicesModule.js b/src/Vault/wwwroot/app/services/servicesModule.js new file mode 100644 index 00000000..0fbfca98 --- /dev/null +++ b/src/Vault/wwwroot/app/services/servicesModule.js @@ -0,0 +1,2 @@ +angular + .module('bit.services', ['ngResource', 'ngStorage', 'angular-jwt']); diff --git a/src/Vault/wwwroot/app/services/tokenService.js b/src/Vault/wwwroot/app/services/tokenService.js new file mode 100644 index 00000000..37cd6b43 --- /dev/null +++ b/src/Vault/wwwroot/app/services/tokenService.js @@ -0,0 +1,27 @@ +angular + .module('bit.services') + + .factory('tokenService', function ($sessionStorage) { + var _service = {}, + _token; + + _service.setToken = function (token) { + $sessionStorage.authBearer = token; + _token = token; + }; + + _service.getToken = function () { + if (!_token) { + _token = $sessionStorage.authBearer; + } + + return _token; + }; + + _service.clearToken = function () { + _token = null; + delete $sessionStorage.authBearer; + }; + + return _service; + }); diff --git a/src/Vault/wwwroot/app/services/validationService.js b/src/Vault/wwwroot/app/services/validationService.js new file mode 100644 index 00000000..c8f43208 --- /dev/null +++ b/src/Vault/wwwroot/app/services/validationService.js @@ -0,0 +1,52 @@ +angular + .module('bit.services') + + .factory('validationService', function () { + var _service = {}; + + _service.addErrors = function (form, reason) { + var data = reason.data; + var defaultErrorMessage = 'An unexpected error has occured.'; + form.$errors = []; + + if (!data || !angular.isObject(data)) { + form.$errors.push(defaultErrorMessage); + return; + } + + if (!data.ValidationErrors) { + if (data.Message) { + form.$errors.push(data.Message); + } + else { + form.$errors.push(defaultErrorMessage); + } + + return; + } + + for (var key in data.ValidationErrors) { + if (!data.ValidationErrors.hasOwnProperty(key)) { + continue; + } + + for (var i = 0; i < data.ValidationErrors[key].length; i++) { + _service.addError(form, key, data.ValidationErrors[key][i]); + } + } + }; + + _service.addError = function (form, key, errorMessage, clearExistingErrors) { + if (clearExistingErrors || !form.$errors) { + form.$errors = []; + } + + form.$errors.push(errorMessage); + if (key && key !== '' && form[key] && form[key].$registerApiError) { + form[key].$registerApiError(); + } + }; + + + return _service; + }); diff --git a/src/Vault/wwwroot/app/settings.js b/src/Vault/wwwroot/app/settings.js new file mode 100644 index 00000000..3e15adc0 --- /dev/null +++ b/src/Vault/wwwroot/app/settings.js @@ -0,0 +1,2 @@ +angular.module('bit') +.constant('appSettings', {"rememberdEmailCookieName":"bit.rememberedEmail","version":"0.0.1","environment":"Development","apiUri":"http://localhost:4000"}); diff --git a/src/Vault/wwwroot/app/settings/settingsChangeEmailController.js b/src/Vault/wwwroot/app/settings/settingsChangeEmailController.js new file mode 100644 index 00000000..f2ef340b --- /dev/null +++ b/src/Vault/wwwroot/app/settings/settingsChangeEmailController.js @@ -0,0 +1,66 @@ +angular + .module('bit.settings') + + .controller('settingsChangeEmailController', function ($scope, $state, apiService, $uibModalInstance, cryptoService, cipherService, authService, $q, toastr) { + var _masterPasswordHash, + _newMasterPasswordHash, + _newKey; + + $scope.token = function (model) { + _masterPasswordHash = cryptoService.hashPassword(model.masterPassword); + + var request = { + newEmail: model.newEmail, + masterPasswordHash: _masterPasswordHash + }; + + $scope.tokenPromise = apiService.accounts.emailToken(request, function () { + _newKey = cryptoService.makeKey(model.masterPassword, model.newEmail); + _newMasterPasswordHash = cryptoService.hashPassword(model.masterPassword, _newKey); + + $scope.tokenSent = true; + }).$promise; + }; + + $scope.confirm = function (model) { + $scope.processing = true; + + var reencryptedSites = []; + var sitesPromise = apiService.sites.list({ dirty: false }, function (encryptedSites) { + var unencryptedSites = cipherService.decryptSites(encryptedSites.Data); + reencryptedSites = cipherService.encryptSites(unencryptedSites, _newKey); + }).$promise; + + var reencryptedFolders = []; + var foldersPromise = apiService.folders.list({ dirty: false }, function (encryptedFolders) { + var unencryptedFolders = cipherService.decryptFolders(encryptedFolders.Data); + reencryptedFolders = cipherService.encryptFolders(unencryptedFolders, _newKey); + }).$promise; + + $q.all([sitesPromise, foldersPromise]).then(function () { + var request = { + token: model.token, + newEmail: model.newEmail, + masterPasswordHash: _masterPasswordHash, + newMasterPasswordHash: _newMasterPasswordHash, + ciphers: reencryptedSites.concat(reencryptedFolders) + }; + + $scope.confirmPromise = apiService.accounts.email(request, function () { + $uibModalInstance.dismiss('cancel'); + authService.logOut(); + $state.go('frontend.login.info').then(function () { + toastr.success('Please log back in.', 'Email Changed') + }); + }, function () { + // TODO: recovery mode + $uibModalInstance.dismiss('cancel'); + toastr.error('Something went wrong.', 'Oh No!'); + }).$promise; + }); + }; + + $scope.close = function () { + $uibModalInstance.dismiss('cancel'); + }; + }); diff --git a/src/Vault/wwwroot/app/settings/settingsChangePasswordController.js b/src/Vault/wwwroot/app/settings/settingsChangePasswordController.js new file mode 100644 index 00000000..844f540a --- /dev/null +++ b/src/Vault/wwwroot/app/settings/settingsChangePasswordController.js @@ -0,0 +1,53 @@ +angular + .module('bit.settings') + + .controller('settingsChangePasswordController', function ($scope, $state, apiService, $uibModalInstance, + cryptoService, authService, cipherService, validationService, $q, toastr) { + $scope.save = function (model, form) { + if ($scope.model.newMasterPassword != $scope.model.confirmNewMasterPassword) { + validationService.addError(form, 'ConfirmNewMasterPassword', 'New master password confirmation does not match.', true); + return; + } + + $scope.processing = true; + + var profile = authService.getUserProfile(); + var newKey = cryptoService.makeKey(model.newMasterPassword, profile.email); + + var reencryptedSites = []; + var sitesPromise = apiService.sites.list({ dirty: false }, function (encryptedSites) { + var unencryptedSites = cipherService.decryptSites(encryptedSites.Data); + reencryptedSites = cipherService.encryptSites(unencryptedSites, newKey); + }).$promise; + + var reencryptedFolders = []; + var foldersPromise = apiService.folders.list({ dirty: false }, function (encryptedFolders) { + var unencryptedFolders = cipherService.decryptFolders(encryptedFolders.Data); + reencryptedFolders = cipherService.encryptFolders(unencryptedFolders, newKey); + }).$promise; + + $q.all([sitesPromise, foldersPromise]).then(function () { + var request = { + masterPasswordHash: cryptoService.hashPassword(model.masterPassword), + newMasterPasswordHash: cryptoService.hashPassword(model.newMasterPassword, newKey), + ciphers: reencryptedSites.concat(reencryptedFolders) + }; + + $scope.savePromise = apiService.accounts.putPassword(request, function () { + $uibModalInstance.dismiss('cancel'); + authService.logOut(); + $state.go('frontend.login.info').then(function () { + toastr.success('Please log back in.', 'Master Password Changed') + }); + }, function () { + // TODO: recovery mode + $uibModalInstance.dismiss('cancel'); + toastr.error('Something went wrong.', 'Oh No!'); + }).$promise; + }); + }; + + $scope.close = function () { + $uibModalInstance.dismiss('cancel'); + }; + }); diff --git a/src/Vault/wwwroot/app/settings/settingsController.js b/src/Vault/wwwroot/app/settings/settingsController.js new file mode 100644 index 00000000..4025ca18 --- /dev/null +++ b/src/Vault/wwwroot/app/settings/settingsController.js @@ -0,0 +1,72 @@ +angular + .module('bit.settings') + + .controller('settingsController', function ($scope, $uibModal, apiService, toastr, authService) { + $scope.model = {}; + + apiService.accounts.getProfile({}, function (user) { + $scope.model = { + name: user.Name, + email: user.Email, + masterPasswordHint: user.MasterPasswordHint, + culture: user.Culture, + twoFactorEnabled: user.TwoFactorEnabled + }; + }); + + $scope.save = function (model) { + $scope.savePromise = apiService.accounts.putProfile({}, model, function (profile) { + authService.setUserProfile(profile); + toastr.success('Account has been updated.', 'Success!'); + }).$promise; + }; + + $scope.changePassword = function () { + $uibModal.open({ + animation: true, + templateUrl: 'app/settings/views/settingsChangePassword.html', + controller: 'settingsChangePasswordController' + }); + }; + + $scope.$on('settingsChangePassword', function (event, args) { + $scope.changePassword(); + }); + + $scope.changeEmail = function () { + $uibModal.open({ + animation: true, + templateUrl: 'app/settings/views/settingsChangeEmail.html', + controller: 'settingsChangeEmailController', + size: 'sm' + }); + }; + + $scope.$on('settingsChangeEmail', function (event, args) { + $scope.changeEmail(); + }); + + $scope.twoFactor = function () { + $uibModal.open({ + animation: true, + templateUrl: 'app/settings/views/settingsTwoFactor.html', + controller: 'settingsTwoFactorController' + }); + }; + + $scope.$on('settingsTwoFactor', function (event, args) { + $scope.twoFactor(); + }); + + $scope.sessions = function () { + $uibModal.open({ + animation: true, + templateUrl: 'app/settings/views/settingsSessions.html', + controller: 'settingsSessionsController' + }); + }; + + $scope.$on('settingsSessions', function (event, args) { + $scope.sessions(); + }); + }); diff --git a/src/Vault/wwwroot/app/settings/settingsModule.js b/src/Vault/wwwroot/app/settings/settingsModule.js new file mode 100644 index 00000000..4c5aa7f7 --- /dev/null +++ b/src/Vault/wwwroot/app/settings/settingsModule.js @@ -0,0 +1,2 @@ +angular + .module('bit.settings', ['ui.bootstrap', 'toastr']); diff --git a/src/Vault/wwwroot/app/settings/settingsSessionsController.js b/src/Vault/wwwroot/app/settings/settingsSessionsController.js new file mode 100644 index 00000000..87fb77e3 --- /dev/null +++ b/src/Vault/wwwroot/app/settings/settingsSessionsController.js @@ -0,0 +1,22 @@ +angular + .module('bit.settings') + + .controller('settingsSessionsController', function ($scope, $state, apiService, $uibModalInstance, cryptoService, authService, toastr) { + $scope.submit = function (model) { + var request = { + masterPasswordHash: cryptoService.hashPassword(model.masterPassword) + }; + + $scope.submitPromise = apiService.accounts.putSecurityStamp(request, function () { + $uibModalInstance.dismiss('cancel'); + authService.logOut(); + $state.go('frontend.login.info').then(function () { + toastr.success('Please log back in.', 'All Sessions Deauthorized') + }); + }).$promise; + }; + + $scope.close = function () { + $uibModalInstance.dismiss('cancel'); + }; + }); diff --git a/src/Vault/wwwroot/app/settings/settingsTwoFactorController.js b/src/Vault/wwwroot/app/settings/settingsTwoFactorController.js new file mode 100644 index 00000000..b621624a --- /dev/null +++ b/src/Vault/wwwroot/app/settings/settingsTwoFactorController.js @@ -0,0 +1,62 @@ +angular + .module('bit.settings') + + .controller('settingsTwoFactorController', function ($scope, apiService, $uibModalInstance, cryptoService, authService, $q, toastr) { + var _issuer = 'bitwarden', + _profile = authService.getUserProfile(), + _masterPasswordHash; + + $scope.account = _profile.email; + $scope.enabled = function () { + return _profile.extended && _profile.extended.twoFactorEnabled; + } + + $scope.auth = function (model) { + _masterPasswordHash = cryptoService.hashPassword(model.masterPassword); + + $scope.authPromise = apiService.accounts.getTwoFactor({ + masterPasswordHash: _masterPasswordHash, + provider: 0 /* Only authenticator provider for now. */ + }, function (response) { + var key = response.AuthenticatorKey; + $scope.twoFactorModel = { + enabled: response.TwoFactorEnabled, + key: key.replace(/(.{4})/g, '$1 ').trim(), + qr: 'https://chart.googleapis.com/chart?chs=120x120&chld=L|0&cht=qr&chl=otpauth://totp/' + + _issuer + ':' + encodeURIComponent(_profile.email) + + '%3Fsecret=' + encodeURIComponent(key) + + '%26issuer=' + _issuer + }; + }).$promise; + }; + + $scope.update = function (model) { + var currentlyEnabled = $scope.twoFactorModel.enabled; + if (currentlyEnabled && !confirm('Are you sure you want to disable two-step login?')) { + return; + } + + var request = { + enabled: !currentlyEnabled, + token: model ? model.token : null, + masterPasswordHash: _masterPasswordHash, + }; + + $scope.updatePromise = apiService.accounts.putTwoFactor({}, request, function (response) { + if (response.TwoFactorEnabled) { + toastr.success('Two-step login has been enabled.'); + if (_profile.extended) _profile.extended.twoFactorEnabled = true; + } + else { + toastr.success('Two-step login has been disabled.'); + if (_profile.extended) _profile.extended.twoFactorEnabled = false; + } + + $scope.close(); + }).$promise; + }; + + $scope.close = function () { + $uibModalInstance.dismiss('cancel'); + }; + }); diff --git a/src/Vault/wwwroot/app/settings/views/settings.html b/src/Vault/wwwroot/app/settings/views/settings.html new file mode 100644 index 00000000..1e3dae90 --- /dev/null +++ b/src/Vault/wwwroot/app/settings/views/settings.html @@ -0,0 +1,46 @@ +
+

+ Settings + manage your account +

+
+
+
+
+

General

+
+
+
+
+

Errors have occured

+
    +
  • {{e}}
  • +
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ +
+
+
\ No newline at end of file diff --git a/src/Vault/wwwroot/app/settings/views/settingsChangeEmail.html b/src/Vault/wwwroot/app/settings/views/settingsChangeEmail.html new file mode 100644 index 00000000..a972939c --- /dev/null +++ b/src/Vault/wwwroot/app/settings/views/settingsChangeEmail.html @@ -0,0 +1,54 @@ + +
+ + +
+
+ + +
+ diff --git a/src/Vault/wwwroot/app/settings/views/settingsChangePassword.html b/src/Vault/wwwroot/app/settings/views/settingsChangePassword.html new file mode 100644 index 00000000..c88bb888 --- /dev/null +++ b/src/Vault/wwwroot/app/settings/views/settingsChangePassword.html @@ -0,0 +1,46 @@ + +
+ + +
+ diff --git a/src/Vault/wwwroot/app/settings/views/settingsSessions.html b/src/Vault/wwwroot/app/settings/views/settingsSessions.html new file mode 100644 index 00000000..4d46373b --- /dev/null +++ b/src/Vault/wwwroot/app/settings/views/settingsSessions.html @@ -0,0 +1,32 @@ + +
+ + +
diff --git a/src/Vault/wwwroot/app/settings/views/settingsTwoFactor.html b/src/Vault/wwwroot/app/settings/views/settingsTwoFactor.html new file mode 100644 index 00000000..74a5f220 --- /dev/null +++ b/src/Vault/wwwroot/app/settings/views/settingsTwoFactor.html @@ -0,0 +1,82 @@ + +
+ + +
+
+ + +
\ No newline at end of file diff --git a/src/Vault/wwwroot/app/tools/toolsAuditsController.js b/src/Vault/wwwroot/app/tools/toolsAuditsController.js new file mode 100644 index 00000000..0cbafe91 --- /dev/null +++ b/src/Vault/wwwroot/app/tools/toolsAuditsController.js @@ -0,0 +1,8 @@ +angular + .module('bit.tools') + + .controller('toolsAuditsController', function ($scope, apiService, $uibModalInstance, toastr) { + $scope.close = function () { + $uibModalInstance.dismiss('cancel'); + }; + }); diff --git a/src/Vault/wwwroot/app/tools/toolsController.js b/src/Vault/wwwroot/app/tools/toolsController.js new file mode 100644 index 00000000..833a1e44 --- /dev/null +++ b/src/Vault/wwwroot/app/tools/toolsController.js @@ -0,0 +1,42 @@ +angular + .module('bit.tools') + + .controller('toolsController', function ($scope, $uibModal, apiService, toastr, authService) { + $scope.import = function () { + $uibModal.open({ + animation: true, + templateUrl: 'app/tools/views/toolsImport.html', + controller: 'toolsImportController', + size: 'sm' + }); + }; + + $scope.$on('toolsImport', function (event, args) { + $scope.import(); + }); + + $scope.export = function () { + $uibModal.open({ + animation: true, + templateUrl: 'app/tools/views/toolsExport.html', + controller: 'toolsExportController', + size: 'sm' + }); + }; + + $scope.$on('toolsExport', function (event, args) { + $scope.export(); + }); + + $scope.audits = function () { + $uibModal.open({ + animation: true, + templateUrl: 'app/tools/views/toolsAudits.html', + controller: 'toolsAuditsController' + }); + }; + + $scope.$on('toolsAudits', function (event, args) { + $scope.audits(); + }); + }); diff --git a/src/Vault/wwwroot/app/tools/toolsExportController.js b/src/Vault/wwwroot/app/tools/toolsExportController.js new file mode 100644 index 00000000..e285b00e --- /dev/null +++ b/src/Vault/wwwroot/app/tools/toolsExportController.js @@ -0,0 +1,71 @@ +angular + .module('bit.tools') + + .controller('toolsExportController', function ($scope, apiService, authService, $uibModalInstance, cryptoService, cipherService, $q, toastr) { + $scope.export = function (model) { + $scope.startedExport = true; + apiService.sites.list({ expand: ['folder'] }, function (sites) { + try { + var decSites = cipherService.decryptSites(sites.Data); + + var exportSites = []; + for (var i = 0; i < decSites.length; i++) { + var site = { + name: decSites[i].name, + uri: decSites[i].uri, + username: decSites[i].username, + password: decSites[i].password, + notes: decSites[i].notes, + folder: decSites[i].folder ? decSites[i].folder.name : null + }; + + exportSites.push(site); + } + + var csvString = Papa.unparse(exportSites); + var csvBlob = new Blob([csvString]); + if (window.navigator.msSaveOrOpenBlob) { // IE hack. ref http://msdn.microsoft.com/en-us/library/ie/hh779016.aspx + window.navigator.msSaveBlob(csvBlob, makeFileName()); + } + else { + var a = window.document.createElement('a'); + a.href = window.URL.createObjectURL(csvBlob, { type: 'text/plain' }); + a.download = makeFileName(); + document.body.appendChild(a); + a.click(); // IE: "Access is denied". ref: https://connect.microsoft.com/IE/feedback/details/797361/ie-10-treats-blob-url-as-cross-origin-and-denies-access + document.body.removeChild(a); + } + + toastr.success('Your data has been exported. Check your browser\'s downloads folder.', 'Success!'); + $scope.close(); + } + catch (err) { + toastr.error('Something went wrong. Please try again.', 'Error!'); + $scope.close(); + } + }, function () { + toastr.error('Something went wrong. Please try again.', 'Error!'); + $scope.close(); + }); + }; + + $scope.close = function () { + $uibModalInstance.dismiss('cancel'); + }; + + function makeFileName() { + var now = new Date(); + var dateString = + now.getFullYear() + '' + padNumber((now.getMonth() + 1), 2) + '' + padNumber(now.getDate(), 2) + + padNumber(now.getHours(), 2) + '' + padNumber(now.getMinutes(), 2) + + padNumber(now.getSeconds(), 2); + + return 'bitwarden_export_' + dateString + '.csv'; + } + + function padNumber(number, width, paddingCharacter) { + paddingCharacter = paddingCharacter || '0'; + number = number + ''; + return number.length >= width ? number : new Array(width - number.length + 1).join(paddingCharacter) + number; + } + }); diff --git a/src/Vault/wwwroot/app/tools/toolsImportController.js b/src/Vault/wwwroot/app/tools/toolsImportController.js new file mode 100644 index 00000000..eb2b7433 --- /dev/null +++ b/src/Vault/wwwroot/app/tools/toolsImportController.js @@ -0,0 +1,8 @@ +angular + .module('bit.tools') + + .controller('toolsImportController', function ($scope, apiService, $uibModalInstance, cryptoService, cipherService, $q, toastr) { + $scope.close = function () { + $uibModalInstance.dismiss('cancel'); + }; + }); diff --git a/src/Vault/wwwroot/app/tools/toolsModule.js b/src/Vault/wwwroot/app/tools/toolsModule.js new file mode 100644 index 00000000..98191f49 --- /dev/null +++ b/src/Vault/wwwroot/app/tools/toolsModule.js @@ -0,0 +1,2 @@ +angular + .module('bit.tools', ['ui.bootstrap', 'toastr']); diff --git a/src/Vault/wwwroot/app/tools/views/tools.html b/src/Vault/wwwroot/app/tools/views/tools.html new file mode 100644 index 00000000..f17906b6 --- /dev/null +++ b/src/Vault/wwwroot/app/tools/views/tools.html @@ -0,0 +1,9 @@ +
+

+ Tools + helpful utilities +

+
+
+ Content +
diff --git a/src/Vault/wwwroot/app/tools/views/toolsAudits.html b/src/Vault/wwwroot/app/tools/views/toolsAudits.html new file mode 100644 index 00000000..adf9a56c --- /dev/null +++ b/src/Vault/wwwroot/app/tools/views/toolsAudits.html @@ -0,0 +1,10 @@ + + + diff --git a/src/Vault/wwwroot/app/tools/views/toolsExport.html b/src/Vault/wwwroot/app/tools/views/toolsExport.html new file mode 100644 index 00000000..cee32b4b --- /dev/null +++ b/src/Vault/wwwroot/app/tools/views/toolsExport.html @@ -0,0 +1,28 @@ + +
+ + +
+ diff --git a/src/Vault/wwwroot/app/tools/views/toolsImport.html b/src/Vault/wwwroot/app/tools/views/toolsImport.html new file mode 100644 index 00000000..44f283c0 --- /dev/null +++ b/src/Vault/wwwroot/app/tools/views/toolsImport.html @@ -0,0 +1,21 @@ + +
+ + +
diff --git a/src/Vault/wwwroot/app/vault/vaultAddFolderController.js b/src/Vault/wwwroot/app/vault/vaultAddFolderController.js new file mode 100644 index 00000000..92fc9d3f --- /dev/null +++ b/src/Vault/wwwroot/app/vault/vaultAddFolderController.js @@ -0,0 +1,17 @@ +angular + .module('bit.vault') + + .controller('vaultAddFolderController', function ($scope, apiService, $uibModalInstance, cryptoService, cipherService) { + $scope.savePromise = null; + $scope.save = function (model) { + var folder = cipherService.encryptFolder(model); + $scope.savePromise = apiService.folders.post(folder, function (response) { + var decFolder = cipherService.decryptFolder(response); + $uibModalInstance.close(decFolder); + }).$promise; + }; + + $scope.close = function () { + $uibModalInstance.dismiss('close'); + }; + }); diff --git a/src/Vault/wwwroot/app/vault/vaultAddSiteController.js b/src/Vault/wwwroot/app/vault/vaultAddSiteController.js new file mode 100644 index 00000000..93ea30f6 --- /dev/null +++ b/src/Vault/wwwroot/app/vault/vaultAddSiteController.js @@ -0,0 +1,47 @@ +angular + .module('bit.vault') + + .controller('vaultAddSiteController', function ($scope, apiService, $uibModalInstance, cryptoService, cipherService, passwordService, folders, selectedFolder) { + $scope.folders = folders; + $scope.site = { + folderId: selectedFolder ? selectedFolder.id : null + }; + + $scope.savePromise = null; + $scope.save = function (model) { + var site = cipherService.encryptSite(model); + $scope.savePromise = apiService.sites.post(site, function (siteResponse) { + var decSite = cipherService.decryptSite(siteResponse); + $uibModalInstance.close(decSite); + }).$promise; + }; + + $scope.generatePassword = function () { + if (!$scope.site.password || confirm('Are you sure you want to overwrite the current password?')) { + $scope.site.password = passwordService.generatePassword({ length: 10, special: true }); + } + }; + + $scope.clipboardSuccess = function (e) { + e.clearSelection(); + selectPassword(e); + }; + + $scope.clipboardError = function (e, password) { + if (password) { + selectPassword(e); + } + alert('Your web browser does not support easy clipboard copying. Copy it manually instead.'); + }; + + function selectPassword(e) { + var target = $(e.trigger).parent().prev(); + if (target.attr('type') == 'text') { + target.select(); + } + } + + $scope.close = function () { + $uibModalInstance.dismiss('close'); + }; + }); diff --git a/src/Vault/wwwroot/app/vault/vaultController.js b/src/Vault/wwwroot/app/vault/vaultController.js new file mode 100644 index 00000000..10f58e24 --- /dev/null +++ b/src/Vault/wwwroot/app/vault/vaultController.js @@ -0,0 +1,155 @@ +angular + .module('bit.vault') + + .controller('vaultController', function ($scope, $uibModal, apiService, $filter, cryptoService, authService, toastr, cipherService) { + $scope.sites = []; + $scope.folders = []; + + apiService.sites.list({}, function (sites) { + var decSites = []; + for (var i = 0; i < sites.Data.length; i++) { + var decSite = { + id: sites.Data[i].Id, + folderId: sites.Data[i].FolderId + }; + + try { decSite.name = cryptoService.decrypt(sites.Data[i].Name); } + catch (err) { decSite.name = "[error: cannot decrypt]"; } + + try { decSite.username = cryptoService.decrypt(sites.Data[i].Username); } + catch (err) { decSite.username = "[error: cannot decrypt]"; } + + decSites.push(decSite); + } + + $scope.sites = decSites; + }); + + apiService.folders.list({}, function (folders) { + var decFolders = [{ + id: null, + name: '(none)' + }]; + + for (var i = 0; i < folders.Data.length; i++) { + var decFolder = { + id: folders.Data[i].Id + }; + + try { decFolder.name = cryptoService.decrypt(folders.Data[i].Name); } + catch (err) { decFolder.name = "[error: cannot decrypt]"; } + + decFolders.push(decFolder); + } + + $scope.folders = decFolders; + }); + + $scope.editSite = function (site) { + var editModel = $uibModal.open({ + animation: true, + templateUrl: 'app/vault/views/vaultEditSite.html', + controller: 'vaultEditSiteController', + resolve: { + siteId: function () { return site.id; }, + folders: function () { return $scope.folders; } + } + }); + + editModel.result.then(function (editedSite) { + var site = $filter('filter')($scope.sites, { id: editedSite.id }, true); + if (site && site.length > 0) { + site[0].folderId = editedSite.folderId; + site[0].name = editedSite.name; + site[0].username = editedSite.username; + } + }); + }; + + $scope.$on('vaultAddSite', function (event, args) { + $scope.addSite(); + }); + + $scope.addSite = function (folder) { + var addModel = $uibModal.open({ + animation: true, + templateUrl: 'app/vault/views/vaultAddSite.html', + controller: 'vaultAddSiteController', + resolve: { + folders: function () { return $scope.folders; }, + selectedFolder: function () { return folder; } + } + }); + + addModel.result.then(function (addedSite) { + $scope.sites.push(addedSite); + }); + }; + + $scope.deleteSite = function (site) { + if (!confirm("Are you sure you want to delete this site (" + site.name + ")?")) { + return; + } + + apiService.sites.del({ id: site.id }, function () { + var index = $scope.sites.indexOf(site); + $scope.sites.splice(index, 1); + }); + }; + + $scope.editFolder = function (folder) { + var editModel = $uibModal.open({ + animation: true, + templateUrl: 'app/vault/views/vaultEditFolder.html', + controller: 'vaultEditFolderController', + size: 'sm', + resolve: { + folderId: function () { return folder.id; } + } + }); + + editModel.result.then(function (editedFolder) { + var folder = $filter('filter')($scope.folders, { id: editedFolder.id }, true); + if (folder && folder.length > 0) { + folder[0].name = editedFolder.name; + } + }); + }; + + $scope.$on('vaultAddFolder', function (event, args) { + $scope.addFolder(); + }); + + $scope.addFolder = function () { + var addModel = $uibModal.open({ + animation: true, + templateUrl: 'app/vault/views/vaultAddFolder.html', + controller: 'vaultAddFolderController', + size: 'sm' + }); + + addModel.result.then(function (addedFolder) { + $scope.folders.push(addedFolder); + }); + }; + + $scope.deleteFolder = function (folder) { + if (!confirm("Are you sure you want to delete this folder (" + folder.name + ")?")) { + return; + } + + apiService.folders.del({ id: folder.id }, function () { + var index = $scope.folders.indexOf(folder); + $scope.folders.splice(index, 1); + }); + }; + + $scope.canDeleteFolder = function (folder) { + if (!folder || !folder.id) { + return false; + } + + var sites = $filter('filter')($scope.sites, { folderId: folder.id }); + return sites.length === 0; + }; + }); diff --git a/src/Vault/wwwroot/app/vault/vaultEditFolderController.js b/src/Vault/wwwroot/app/vault/vaultEditFolderController.js new file mode 100644 index 00000000..e23bfb4a --- /dev/null +++ b/src/Vault/wwwroot/app/vault/vaultEditFolderController.js @@ -0,0 +1,23 @@ +angular + .module('bit.vault') + + .controller('vaultEditFolderController', function ($scope, apiService, $uibModalInstance, cryptoService, cipherService, folderId) { + $scope.folder = {}; + + apiService.folders.get({ id: folderId }, function (folder) { + $scope.folder = cipherService.decryptFolder(folder); + }); + + $scope.savePromise = null; + $scope.save = function (model) { + var folder = cipherService.encryptFolder(model); + $scope.savePromise = apiService.folders.put({ id: folderId }, folder, function (response) { + var decFolder = cipherService.decryptFolder(response); + $uibModalInstance.close(decFolder); + }).$promise; + }; + + $scope.close = function () { + $uibModalInstance.dismiss('cancel'); + }; + }); diff --git a/src/Vault/wwwroot/app/vault/vaultEditSiteController.js b/src/Vault/wwwroot/app/vault/vaultEditSiteController.js new file mode 100644 index 00000000..0fc210d1 --- /dev/null +++ b/src/Vault/wwwroot/app/vault/vaultEditSiteController.js @@ -0,0 +1,48 @@ +angular + .module('bit.vault') + + .controller('vaultEditSiteController', function ($scope, apiService, $uibModalInstance, cryptoService, cipherService, passwordService, siteId, folders) { + $scope.folders = folders; + $scope.site = {}; + + apiService.sites.get({ id: siteId }, function (site) { + $scope.site = cipherService.decryptSite(site); + }); + + $scope.save = function (model) { + var site = cipherService.encryptSite(model); + $scope.savePromise = apiService.sites.put({ id: siteId }, site, function (siteResponse) { + var decSite = cipherService.decryptSite(siteResponse); + $uibModalInstance.close(decSite); + }).$promise; + }; + + $scope.generatePassword = function () { + if (!$scope.site.password || confirm('Are you sure you want to overwrite the current password?')) { + $scope.site.password = passwordService.generatePassword({ length: 10, special: true }); + } + }; + + $scope.clipboardSuccess = function (e) { + e.clearSelection(); + selectPassword(e); + }; + + $scope.clipboardError = function (e, password) { + if (password) { + selectPassword(e); + } + alert('Your web browser does not support easy clipboard copying. Copy it manually instead.'); + }; + + function selectPassword(e) { + var target = $(e.trigger).parent().prev(); + if (target.attr('type') == 'text') { + target.select(); + } + } + + $scope.close = function () { + $uibModalInstance.dismiss('cancel'); + }; + }); diff --git a/src/Vault/wwwroot/app/vault/vaultModule.js b/src/Vault/wwwroot/app/vault/vaultModule.js new file mode 100644 index 00000000..84125898 --- /dev/null +++ b/src/Vault/wwwroot/app/vault/vaultModule.js @@ -0,0 +1,2 @@ +angular + .module('bit.vault', ['ui.bootstrap', 'ngclipboard']); diff --git a/src/Vault/wwwroot/app/vault/views/vault.html b/src/Vault/wwwroot/app/vault/views/vault.html new file mode 100644 index 00000000..3a969cb9 --- /dev/null +++ b/src/Vault/wwwroot/app/vault/views/vault.html @@ -0,0 +1,51 @@ +
+

+ My Vault + safe and secure +

+
+
+
+
+

{{folder.name}}

+
+ + + +
+
+
+
+

No sites in this folder.

+ +
+
+ + + + + + + + + + + + + + + +
SiteUsername
{{site.name}}{{site.username}} + + +
+
+
+
+
\ No newline at end of file diff --git a/src/Vault/wwwroot/app/vault/views/vaultAddFolder.html b/src/Vault/wwwroot/app/vault/views/vaultAddFolder.html new file mode 100644 index 00000000..703a6207 --- /dev/null +++ b/src/Vault/wwwroot/app/vault/views/vaultAddFolder.html @@ -0,0 +1,24 @@ + +
+ + +
\ No newline at end of file diff --git a/src/Vault/wwwroot/app/vault/views/vaultAddSite.html b/src/Vault/wwwroot/app/vault/views/vaultAddSite.html new file mode 100644 index 00000000..21f0f62d --- /dev/null +++ b/src/Vault/wwwroot/app/vault/views/vaultAddSite.html @@ -0,0 +1,92 @@ + +
+ + +
\ No newline at end of file diff --git a/src/Vault/wwwroot/app/vault/views/vaultEditFolder.html b/src/Vault/wwwroot/app/vault/views/vaultEditFolder.html new file mode 100644 index 00000000..29751080 --- /dev/null +++ b/src/Vault/wwwroot/app/vault/views/vaultEditFolder.html @@ -0,0 +1,24 @@ + +
+ + +
\ No newline at end of file diff --git a/src/Vault/wwwroot/app/vault/views/vaultEditSite.html b/src/Vault/wwwroot/app/vault/views/vaultEditSite.html new file mode 100644 index 00000000..c390f671 --- /dev/null +++ b/src/Vault/wwwroot/app/vault/views/vaultEditSite.html @@ -0,0 +1,95 @@ + +
+ + +
\ No newline at end of file diff --git a/src/Vault/wwwroot/app/views/backendLayout.html b/src/Vault/wwwroot/app/views/backendLayout.html new file mode 100644 index 00000000..615f9a01 --- /dev/null +++ b/src/Vault/wwwroot/app/views/backendLayout.html @@ -0,0 +1,78 @@ +
+
+ + +
+ + + +
+
+ +
+ + Copyright © , bitwarden.com +
+
\ No newline at end of file diff --git a/src/Vault/wwwroot/app/views/frontendLayout.html b/src/Vault/wwwroot/app/views/frontendLayout.html new file mode 100644 index 00000000..47e1b0a2 --- /dev/null +++ b/src/Vault/wwwroot/app/views/frontendLayout.html @@ -0,0 +1,2 @@ +
+
\ No newline at end of file diff --git a/src/Vault/wwwroot/favicon.ico b/src/Vault/wwwroot/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..f2aadce414698ec4dc1d9063bdf1d78c231a15e2 GIT binary patch literal 1150 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

@1b!Id0GMw{r(gw)+8+lbOopSLNS+ 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 z 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

rl5%ZX>1f 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 literal 0 HcmV?d00001 diff --git a/src/Vault/wwwroot/index.html b/src/Vault/wwwroot/index.html new file mode 100644 index 00000000..81215e05 --- /dev/null +++ b/src/Vault/wwwroot/index.html @@ -0,0 +1,124 @@ + + + + + + + + bitwarden.com Password Manager + + + + + + + + + + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Vault/wwwroot/web.config b/src/Vault/wwwroot/web.config new file mode 100644 index 00000000..e780518b --- /dev/null +++ b/src/Vault/wwwroot/web.config @@ -0,0 +1,9 @@ + + + + + + + + +