Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
B
Breeze
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
3
Issues
3
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
DeStream-public
Breeze
Commits
72c7a83c
Commit
72c7a83c
authored
Mar 15, 2017
by
Jeremy Bokobza
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added Safe recovery
parent
cd4e3f8f
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
287 additions
and
92 deletions
+287
-92
.gitignore
.gitignore
+1
-0
ControllersTests.cs
Breeze.Api/src/Breeze.Api.Tests/ControllersTests.cs
+98
-3
Safe.postman_collection.json
...e.Api.Tests/Postman requests/Safe.postman_collection.json
+23
-3
SafeController.cs
Breeze.Api/src/Breeze.Api/Controllers/SafeController.cs
+38
-0
SafeCreation.cs
Breeze.Api/src/Breeze.Api/Models/SafeCreation.cs
+45
-28
ISafeWrapper.cs
Breeze.Api/src/Breeze.Api/Wrappers/ISafeWrapper.cs
+10
-8
SafeWrapper.cs
Breeze.Api/src/Breeze.Api/Wrappers/SafeWrapper.cs
+72
-50
No files found.
.gitignore
View file @
72c7a83c
...
...
@@ -8,3 +8,4 @@
/Breeze.Api/src/Breeze.Api/bin
/Breeze.Api/src/Breeze.Api/obj
*.user
/Breeze.Api/src/Breeze.Api/Wallets
Breeze.Api/src/Breeze.Api.Tests/ControllersTests.cs
View file @
72c7a83c
using
Microsoft.AspNetCore.Mvc
;
using
System.Collections.Generic
;
using
System.IO
;
using
Microsoft.AspNetCore.Mvc
;
using
Xunit
;
using
Moq
;
using
Breeze.Api.Controllers
;
...
...
@@ -10,9 +12,9 @@ namespace Breeze.Api.Tests
public
class
ControllersTests
{
[
Fact
]
public
void
CreateSafe
s
uccessfullyReturnsMnemonic
()
public
void
CreateSafe
S
uccessfullyReturnsMnemonic
()
{
var
mockSafeCreate
=
new
Mock
<
ISafeWrapper
>();
var
mockSafeCreate
=
new
Mock
<
ISafeWrapper
>();
mockSafeCreate
.
Setup
(
safe
=>
safe
.
Create
(
It
.
IsAny
<
string
>(),
It
.
IsAny
<
string
>(),
It
.
IsAny
<
string
>(),
It
.
IsAny
<
string
>())).
Returns
(
"mnemonic"
);
var
controller
=
new
SafeController
(
mockSafeCreate
.
Object
);
...
...
@@ -27,9 +29,102 @@ namespace Breeze.Api.Tests
});
// Assert
mockSafeCreate
.
VerifyAll
();
var
viewResult
=
Assert
.
IsType
<
JsonResult
>(
result
);
Assert
.
Equal
(
"mnemonic"
,
viewResult
.
Value
);
Assert
.
NotNull
(
result
);
}
[
Fact
]
public
void
LoadSafeSuccessfullyReturnsSafeModel
()
{
SafeModel
safeModel
=
new
SafeModel
{
FileName
=
"myWallet"
,
Network
=
"MainNet"
,
Addresses
=
new
List
<
string
>
{
"address1"
,
"address2"
,
"address3"
,
"address4"
,
"address5"
}
};
var
mockSafeWrapper
=
new
Mock
<
ISafeWrapper
>();
mockSafeWrapper
.
Setup
(
safe
=>
safe
.
Recover
(
It
.
IsAny
<
string
>(),
It
.
IsAny
<
string
>(),
It
.
IsAny
<
string
>(),
It
.
IsAny
<
string
>(),
It
.
IsAny
<
string
>())).
Returns
(
safeModel
);
var
controller
=
new
SafeController
(
mockSafeWrapper
.
Object
);
// Act
var
result
=
controller
.
Recover
(
new
SafeRecoveryModel
{
Name
=
"myName"
,
FolderPath
=
""
,
Password
=
""
,
Network
=
""
,
Mnemonic
=
"mnemonic"
});
// Assert
mockSafeWrapper
.
VerifyAll
();
var
viewResult
=
Assert
.
IsType
<
JsonResult
>(
result
);
Assert
.
NotNull
(
viewResult
.
Value
);
Assert
.
IsType
<
SafeModel
>(
viewResult
.
Value
);
var
model
=
viewResult
.
Value
as
SafeModel
;
Assert
.
Equal
(
"myWallet"
,
model
.
FileName
);
}
[
Fact
]
public
void
RecoverSafeSuccessfullyReturnsSafeModel
()
{
SafeModel
safeModel
=
new
SafeModel
{
FileName
=
"myWallet"
,
Network
=
"MainNet"
,
Addresses
=
new
List
<
string
>
{
"address1"
,
"address2"
,
"address3"
,
"address4"
,
"address5"
}
};
var
mockSafeWrapper
=
new
Mock
<
ISafeWrapper
>();
mockSafeWrapper
.
Setup
(
safe
=>
safe
.
Load
(
It
.
IsAny
<
string
>(),
It
.
IsAny
<
string
>(),
It
.
IsAny
<
string
>())).
Returns
(
safeModel
);
var
controller
=
new
SafeController
(
mockSafeWrapper
.
Object
);
// Act
var
result
=
controller
.
Load
(
new
SafeLoadModel
{
Name
=
"myName"
,
FolderPath
=
""
,
Password
=
""
});
// Assert
mockSafeWrapper
.
VerifyAll
();
var
viewResult
=
Assert
.
IsType
<
JsonResult
>(
result
);
Assert
.
NotNull
(
viewResult
.
Value
);
Assert
.
IsType
<
SafeModel
>(
viewResult
.
Value
);
var
model
=
viewResult
.
Value
as
SafeModel
;
Assert
.
Equal
(
"myWallet"
,
model
.
FileName
);
}
[
Fact
]
public
void
FileNotFoundExceptionandReturns404
()
{
var
mockSafeWrapper
=
new
Mock
<
ISafeWrapper
>();
mockSafeWrapper
.
Setup
(
safe
=>
safe
.
Load
(
It
.
IsAny
<
string
>(),
It
.
IsAny
<
string
>(),
It
.
IsAny
<
string
>())).
Throws
<
FileNotFoundException
>();
var
controller
=
new
SafeController
(
mockSafeWrapper
.
Object
);
// Act
var
result
=
controller
.
Load
(
new
SafeLoadModel
{
Name
=
"myName"
,
FolderPath
=
""
,
Password
=
""
});
// Assert
mockSafeWrapper
.
VerifyAll
();
var
viewResult
=
Assert
.
IsType
<
ObjectResult
>(
result
);
Assert
.
NotNull
(
viewResult
);
Assert
.
Equal
(
404
,
viewResult
.
StatusCode
);
}
}
}
Breeze.Api/src/Breeze.Api.Tests/Postman requests/Safe.postman_collection.json
View file @
72c7a83c
...
...
@@ -8,7 +8,7 @@
},
"item"
:
[
{
"name"
:
"Create
wallet
- success"
,
"name"
:
"Create
safe
- success"
,
"request"
:
{
"url"
:
"http://localhost:5000/api/safe/"
,
"method"
:
"POST"
,
...
...
@@ -28,7 +28,7 @@
"response"
:
[]
},
{
"name"
:
"Create
wallet
- validation errors"
,
"name"
:
"Create
safe
- validation errors"
,
"request"
:
{
"url"
:
"http://localhost:5000/api/safe/"
,
"method"
:
"POST"
,
...
...
@@ -48,7 +48,7 @@
"response"
:
[]
},
{
"name"
:
"Load
wallet
"
,
"name"
:
"Load
safe
"
,
"request"
:
{
"url"
:
"http://localhost:5000/api/safe/?password=123456&folderPath=MyWallets&name=myFirstWallet"
,
"method"
:
"GET"
,
...
...
@@ -66,6 +66,26 @@
"description"
:
""
},
"response"
:
[]
},
{
"name"
:
"Recover safe"
,
"request"
:
{
"url"
:
"http://localhost:5000/api/safe/recover"
,
"method"
:
"POST"
,
"header"
:
[
{
"key"
:
"Content-Type"
,
"value"
:
"application/json"
,
"description"
:
""
}
],
"body"
:
{
"mode"
:
"raw"
,
"raw"
:
"{
\n\t\"
password
\"
:
\"
123456
\"
,
\n\t\"
network
\"
:
\"
Main
\"
,
\n\t\"
folderPath
\"
:
\"
Wallets
\"
,
\n\t\"
name
\"
:
\"
myFirstWalletRecovered
\"
,
\n\t\"
mnemonic
\"
:
\"
elbow scale error joke labor page beyond curve indicate exit brass laundry
\"\n\t\n
}"
},
"description"
:
""
},
"response"
:
[]
}
]
}
\ No newline at end of file
Breeze.Api/src/Breeze.Api/Controllers/SafeController.cs
View file @
72c7a83c
...
...
@@ -84,5 +84,43 @@ namespace Breeze.Api.Controllers
return
this
.
StatusCode
((
int
)
HttpStatusCode
.
BadRequest
,
e
.
Message
);
}
}
[
Route
(
"recover"
)]
[
HttpPost
]
public
IActionResult
Recover
([
FromBody
]
SafeRecoveryModel
safeRecovery
)
{
// checks the request is valid
if
(!
this
.
ModelState
.
IsValid
)
{
var
errors
=
this
.
ModelState
.
Values
.
SelectMany
(
e
=>
e
.
Errors
.
Select
(
m
=>
m
.
ErrorMessage
));
return
this
.
BadRequest
(
string
.
Join
(
Environment
.
NewLine
,
errors
));
}
try
{
var
safe
=
this
.
safeWrapper
.
Recover
(
safeRecovery
.
Password
,
safeRecovery
.
FolderPath
,
safeRecovery
.
Name
,
safeRecovery
.
Network
,
safeRecovery
.
Mnemonic
);
return
this
.
Json
(
safe
);
}
catch
(
FileNotFoundException
e
)
{
Console
.
WriteLine
(
e
);
// indicates that this wallet does not exist
return
this
.
StatusCode
((
int
)
HttpStatusCode
.
NotFound
,
"Wallet not found."
);
}
catch
(
SecurityException
e
)
{
Console
.
WriteLine
(
e
);
// indicates that the password is wrong
return
this
.
StatusCode
((
int
)
HttpStatusCode
.
Forbidden
,
"Wrong password, please try again."
);
}
catch
(
Exception
e
)
{
Console
.
WriteLine
(
e
);
return
this
.
StatusCode
((
int
)
HttpStatusCode
.
BadRequest
,
e
.
Message
);
}
}
}
}
Breeze.Api/src/Breeze.Api/Models/SafeCreation.cs
View file @
72c7a83c
...
...
@@ -4,41 +4,58 @@ using System.ComponentModel.DataAnnotations;
namespace
Breeze.Api.Models
{
/// <summary>
/// Object used to create a new wallet
/// </summary>
public
class
SafeCreationModel
{
[
Required
(
ErrorMessage
=
"A password is required."
)]
public
string
Password
{
get
;
set
;
}
/// <summary>
/// Object used to create a new wallet
/// </summary>
public
class
SafeCreationModel
{
[
Required
(
ErrorMessage
=
"A password is required."
)]
public
string
Password
{
get
;
set
;
}
public
string
Network
{
get
;
set
;
}
public
string
Network
{
get
;
set
;
}
[
Required
(
ErrorMessage
=
"The folder path where the wallet
will be created is required."
)]
public
string
FolderPath
{
get
;
set
;
}
[
Required
(
ErrorMessage
=
"The folder path where the safe
will be created is required."
)]
public
string
FolderPath
{
get
;
set
;
}
[
Required
(
ErrorMessage
=
"The name of the wallet
to create is missing."
)]
public
string
Name
{
get
;
set
;
}
}
[
Required
(
ErrorMessage
=
"The name of the safe
to create is missing."
)]
public
string
Name
{
get
;
set
;
}
}
public
class
SafeLoadModel
{
[
Required
(
ErrorMessage
=
"A password is required."
)]
public
string
Password
{
get
;
set
;
}
public
class
SafeLoadModel
{
[
Required
(
ErrorMessage
=
"A password is required."
)]
public
string
Password
{
get
;
set
;
}
[
Required
(
ErrorMessage
=
"The folder path is required."
)]
public
string
FolderPath
{
get
;
set
;
}
[
Required
(
ErrorMessage
=
"The folder path is required."
)]
public
string
FolderPath
{
get
;
set
;
}
[
Required
(
ErrorMessage
=
"The name of the wallet
is missing."
)]
public
string
Name
{
get
;
set
;
}
}
[
Required
(
ErrorMessage
=
"The name of the safe
is missing."
)]
public
string
Name
{
get
;
set
;
}
}
public
class
SafeModel
{
public
string
Network
{
get
;
set
;
}
public
class
SafeRecoveryModel
{
[
Required
(
ErrorMessage
=
"A mnemonic is required."
)]
public
string
Mnemonic
{
get
;
set
;
}
public
string
FileName
{
get
;
set
;
}
[
Required
(
ErrorMessage
=
"A password is required."
)]
public
string
Password
{
get
;
set
;
}
public
IEnumerable
<
string
>
Addresses
{
get
;
set
;
}
}
[
Required
(
ErrorMessage
=
"The folder path is required."
)]
public
string
FolderPath
{
get
;
set
;
}
[
Required
(
ErrorMessage
=
"The name of the safe is missing."
)]
public
string
Name
{
get
;
set
;
}
public
string
Network
{
get
;
set
;
}
}
public
class
SafeModel
{
public
string
Network
{
get
;
set
;
}
public
string
FileName
{
get
;
set
;
}
public
IEnumerable
<
string
>
Addresses
{
get
;
set
;
}
}
}
Breeze.Api/src/Breeze.Api/Wrappers/ISafeWrapper.cs
View file @
72c7a83c
...
...
@@ -2,13 +2,15 @@
namespace
Breeze.Api.Wrappers
{
/// <summary>
/// An interface enabling wallet operations.
/// </summary>
public
interface
ISafeWrapper
{
string
Create
(
string
password
,
string
folderPath
,
string
name
,
string
network
);
/// <summary>
/// An interface enabling wallet operations.
/// </summary>
public
interface
ISafeWrapper
{
string
Create
(
string
password
,
string
folderPath
,
string
name
,
string
network
);
SafeModel
Load
(
string
password
,
string
folderPath
,
string
name
);
}
SafeModel
Load
(
string
password
,
string
folderPath
,
string
name
);
SafeModel
Recover
(
string
password
,
string
folderPath
,
string
name
,
string
network
,
string
mnemonic
);
}
}
Breeze.Api/src/Breeze.Api/Wrappers/SafeWrapper.cs
View file @
72c7a83c
...
...
@@ -6,57 +6,79 @@ using Breeze.Api.Models;
namespace
Breeze.Api.Wrappers
{
/// <summary>
/// An implementation of the <see cref="ISafeWrapper"/> interface.
/// </summary>
public
class
SafeWrapper
:
ISafeWrapper
{
/// <summary>
/// Creates a safe on the local device.
/// </summary>
/// <param name="password">The user's password.</param>
/// <param name="folderPath">The folder where the safe will be saved.</param>
/// <param name="name">The name of the safe.</param>
/// <param name="network">The network for which to create a safe.</param>
/// <returns>A mnemonic allowing recovery of the safe.</returns>
public
string
Create
(
string
password
,
string
folderPath
,
string
name
,
string
network
)
{
// any network different than MainNet will default to TestNet
Network
net
;
switch
(
network
.
ToLowerInvariant
())
{
case
"main"
:
case
"mainnet"
:
net
=
Network
.
Main
;
break
;
default
:
net
=
Network
.
TestNet
;
break
;
}
/// <summary>
/// An implementation of the <see cref="ISafeWrapper"/> interface.
/// </summary>
public
class
SafeWrapper
:
ISafeWrapper
{
/// <summary>
/// Creates a safe on the local device.
/// </summary>
/// <param name="password">The user's password.</param>
/// <param name="folderPath">The folder where the safe will be saved.</param>
/// <param name="name">The name of the safe.</param>
/// <param name="network">The network for which to create a safe.</param>
/// <returns>A mnemonic allowing recovery of the safe.</returns>
public
string
Create
(
string
password
,
string
folderPath
,
string
name
,
string
network
)
{
Mnemonic
mnemonic
;
Safe
safe
=
Safe
.
Create
(
out
mnemonic
,
password
,
Path
.
Combine
(
folderPath
,
$"
{
name
}
.json"
),
this
.
GetNetwork
(
network
));
return
mnemonic
.
ToString
();
}
Mnemonic
mnemonic
;
Safe
safe
=
Safe
.
Create
(
out
mnemonic
,
password
,
Path
.
Combine
(
folderPath
,
$"
{
name
}
.json"
),
net
);
return
mnemonic
.
ToString
();
}
/// <summary>
/// Loads a safe from the local device.
/// </summary>
/// <param name="password">The user's password.</param>
/// <param name="folderPath">The folder where the safe will be loaded.</param>
/// <param name="name">The name of the safe.</param>
/// <returns>The safe loaded from the local device</returns>
public
SafeModel
Load
(
string
password
,
string
folderPath
,
string
name
)
{
Safe
safe
=
Safe
.
Load
(
password
,
Path
.
Combine
(
folderPath
,
$"
{
name
}
.json"
));
/// <summary>
/// Loads a safe from the local device.
/// </summary>
/// <param name="password">The user's password.</param>
/// <param name="folderPath">The folder where the safe will be loaded.</param>
/// <param name="name">The name of the safe.</param>
/// <returns>The safe loaded from the local device</returns>
public
SafeModel
Load
(
string
password
,
string
folderPath
,
string
name
)
{
Safe
safe
=
Safe
.
Load
(
password
,
Path
.
Combine
(
folderPath
,
$"
{
name
}
.json"
));
//TODO review here which data should be returned
return
new
SafeModel
{
Network
=
safe
.
Network
.
Name
,
Addresses
=
safe
.
GetFirstNAddresses
(
10
).
Select
(
a
=>
a
.
ToWif
()),
FileName
=
safe
.
WalletFilePath
};
}
//TODO review here which data should be returned
return
new
SafeModel
{
Network
=
safe
.
Network
.
Name
,
Addresses
=
safe
.
GetFirstNAddresses
(
10
).
Select
(
a
=>
a
.
ToWif
()),
FileName
=
safe
.
WalletFilePath
};
}
}
/// <summary>
/// Recovers a safe from the local device.
/// </summary>
/// <param name="password">The user's password.</param>
/// <param name="folderPath">The folder where the safe will be loaded.</param>
/// <param name="name">The name of the safe.</param>
/// <param name="network">The network in which to creae this wallet</param>
/// <param name="mnemonic">The user's mnemonic for the safe.</param>
/// <returns></returns>
public
SafeModel
Recover
(
string
password
,
string
folderPath
,
string
name
,
string
network
,
string
mnemonic
)
{
Safe
safe
=
Safe
.
Recover
(
new
Mnemonic
(
mnemonic
),
password
,
Path
.
Combine
(
folderPath
,
$"
{
name
}
.json"
),
this
.
GetNetwork
(
network
));
//TODO review here which data should be returned
return
new
SafeModel
{
Network
=
safe
.
Network
.
Name
,
Addresses
=
safe
.
GetFirstNAddresses
(
10
).
Select
(
a
=>
a
.
ToWif
()),
FileName
=
safe
.
WalletFilePath
};
}
private
Network
GetNetwork
(
string
network
)
{
// any network different than MainNet will default to TestNet
switch
(
network
.
ToLowerInvariant
())
{
case
"main"
:
case
"mainnet"
:
return
Network
.
Main
;
default
:
return
Network
.
TestNet
;
}
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment