Skip to content

Commit

Permalink
merged APIfixes
Browse files Browse the repository at this point in the history
  • Loading branch information
silkroadnomad committed Jan 9, 2019
2 parents b57a80f + dc83b7a commit f48084f
Show file tree
Hide file tree
Showing 8 changed files with 202 additions and 55 deletions.
147 changes: 130 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,14 @@ Required settings for each dApp namecoin daemon. It contains ``host``, ``port``,

##### Doi Mail Fetch Url
The Url for fetching the doi mail data. Only required for the Send dApp. The Url will be called with a ``get`` request. The dApp expects following answer:
```
```json
{
"data": {
from: "fancy@newsletter.com",
subject: "Fancy Newsletter Confirmation",
redirect: "http://fancynewsletterconfirmationpage.com",
returnPath: "noreply@newsletter.com",
content: "<html><body><a href=\"${confirmation_url}\">Confirmation link</a></body></html>"
"from": "fancy@newsletter.com",
"subject": "Fancy Newsletter Confirmation",
"redirect": "http://fancynewsletterconfirmationpage.com",
"returnPath": "noreply@newsletter.com",
"content": "<html><body><a href=\"${confirmation_url}\">Confirmation link</a></body></html>"
}
}
```
Expand All @@ -72,7 +72,7 @@ The Url for fetching the doi mail data. Only required for the Send dApp. The Url
The SMTP settings of the Confirm dApp for sending double Opt-In mails. Required fields are ``username``, ``password``, ``server`` and ``port``

Example configuration with all three dApps activated:
```
```json
{
"app": {
"types": ["send", "confirm", "verify"]
Expand All @@ -91,7 +91,7 @@ Example configuration with all three dApps activated:
"username": "admin",
"password": "****",
"server": "smtp.your-email.com",
"port": 587
"port": 587,
"defaultFrom": "doichain@your-email.com"
},
"doichain": {
Expand Down Expand Up @@ -125,8 +125,13 @@ You need a valide token for some of the REST calls. Get the token with:
+ ``username`` - Authentification Username
+ ``password`` - Authentification Password

Response with valide credentials:
* Example request (cURL)
```sh
curl -H "Content-Type: application/json" -X POST -d '{"username":"username","password":"password"}' http://localhost:3000/api/v1/login
```

* Response with valid credentials:
```json
{
"status": "success",
"data": {
Expand All @@ -152,7 +157,33 @@ X-User-Id: 8BxFMSZAc7Ez2iiR6
+ ``recipient_mail`` - Email of the recipient
+ ``sender_mail`` - Email of the sender
+ ``ownerid`` - (ADMIN ONLY) Userid of Opt-In-owner
+ ``data`` - (OPTIONAL) JSON string with recipient/Opt-In data
+ ``data`` - (OPTIONAL) Recipient/Opt-In data
- ``screenshot`` - (OPTIONAL) Can store a screenshot of the subscription
- ``templateParam`` - (OPTIONAL) Parameters to be added to template URL
- ``redirectParam`` - (OPTIONAL) Parameters to be added to redirect URL
* Example request:
```sh
curl -X POST -H "X-Auth-Token: Ui5rDPEf2kCugdAafUoU7Mh7--bkkL5hm3lVg6DN132" -H "X-User-Id: szkkeuSpfKueyskLz" http://localhost:3000/api/v1/opt-in -d '{"recipient_mail:recipentMail", "sender_mail":"Sendermail", "data":{"redirectParam":{"id":"hash"}}}'
```
* Success-Response:
```json
{
"status" : "success",
"data" :
{
"id" : "optinId",
"status" : "success",
"message" : "Opt-In added"
}
}
```
* Fail-Response:
```json
{
"status" : "fail",
"message" : "Errormessage"
}
```
##### Export
* Auth required: yes
* Role required: ``none``
Expand All @@ -161,8 +192,52 @@ X-User-Id: 8BxFMSZAc7Ez2iiR6
* Query-Parameter:
+ ``status`` - not yet working
+ ``ownerid`` - (ADMIN ONLY,OPTIONAL) userId of specific Opt-in owner


* Example request:
```sh
curl -X GET -H "X-Auth-Token: BbTe9w3DTZhPNriUWv1aU6a_FDawlkYjKMQ6I2t3V2k"-H "X-User-Id: 8BxFMSZAc7Ez2iiR6" http://localhost:3000/api/v1/export
```
* Success-Response:
```json
{
"data": {
"status": "success",
"data": [
{
"_id": "EFxZCfAx7JqosrQ2E",
"ownerId": "qWgndg2gmsYZqCqin",
"createdAt": "2019-01-04T12:50:46.946Z",
"nameId": "60ADC586B8F03530100CA0BB524572B1664B8A43F7161B5F3D0197B3CD0ED2EB",
"confirmedAt": "2019-01-04T12:51:12.974Z",
"RecipientEmail": {
"email": "bob@ci-doichain.org"
},
"SenderEmail": {
"email": "alice-a@ci-doichain.org"
}
},
{
"_id": "z7HotbvPRG2tsuvd4",
"ownerId": "qWgndg2gmsYZqCqin",
"createdAt": "2019-01-04T12:51:19.115Z",
"nameId": "157305C71AE0C10A2C65B9D4CA19BF3104255DD307EAC4E6B32B8BAB422EC004",
"confirmedAt": "2019-01-04T12:51:38.012Z",
"RecipientEmail": {
"email": "bob@ci-doichain.org"
},
"SenderEmail": {
"email": "alice-b@ci-doichain.org"
}
}
]
}
```
* Fail-Response:
```json
{
"status" : "fail",
"message" : "Errormessage"
}
```
##### Get Double Opt-In mail data
* Auth required: false
* Url: ``doi-mail``
Expand Down Expand Up @@ -212,20 +287,58 @@ X-User-Id: 8BxFMSZAc7Ez2iiR6
- ``returnPath`` - (OPTIONAL) Return Path
- ``templateURL`` - (OPTIONAL) Confirm mail template URL

* Success-Response:
```json
{
"status" : "success",
"data" :
{
"userid" : "userid",
}
}
```
* Fail-Response:
```json
{
"status" : "fail",
"message" : "Errormessage"
}
```

##### Update User
* Auth required: Yes
* Role required: ``admin``
* Url: ``users``
* Role required: none
* Url: ``users/:userId``
* Method: ``PUT``
* Parameter:
+ ``mailTemplate`` - Changed form information as JSON
- ``subject`` - (OPTIONAL) Subject of the email
- ``redirect`` - (OPTIONAL) Redirect URL
- ``returnPath`` - (OPTIONAL) Return Path
- ``templateURL`` - (OPTIONAL) Confirm mail template URL


- ``templateURL`` - (OPTIONAL) Confirm mail template URLhttp://localhost:3000/api/v1/export
* Note: This uses ``PUT`` method. It will overwrite all data in ``mailTemplate`` !
* Example request:
```sh
curl -X PUT -H "X-Auth-Token: BbTe9w3DTZhPNriUWv1aU6a_FDawlkYjKMQ6I2t3V2k"-H "X-User-Id: 8BxFMSZAc7Ez2iiR6" http://localhost:3000/api/v1/users/8BxFMSZAc7Ez2iiR6 -d '{"mailTemplate":{"subject":"changedSubject","redirect":"RedirectPage","returnPath":"ReturnAddress","templateURL":"changedTemplateURL"}}'
```
* Success-Response:
```json
{
"status" : "success",
"data" :
{
"subject" : "changedSubject",
"templateURL" : "changedTemplateURL",
}
}
```
* Fail-Response:
```json
{
"status" : "fail",
"message" : "Errormessage"
}
```
## Blockchain entry name id
The name id is a 256-bit, ECDSA valid, number represanted as a 32 byte (64 characters) string (Same as every Bitcoin privateKey). See also: https://en.bitcoin.it/wiki/Private_key
## UML
Expand Down
7 changes: 4 additions & 3 deletions imports/modules/server/dapps/export_dois.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,14 @@ const exportDois = (data) => {
then: "$$PRUNE",
else: "$$KEEP" }}});
}
pipeline.concat([
pipeline=[...pipeline,
{ $lookup: { from: "recipients", localField: "recipient", foreignField: "_id", as: "RecipientEmail" } },
{ $lookup: { from: "senders", localField: "sender", foreignField: "_id", as: "SenderEmail" } },
{ $unwind: "$SenderEmail"},
{ $unwind: "$RecipientEmail"},
{ $project: {"_id":1,"createdAt":1, "confirmedAt":1,"nameId":1, "SenderEmail.email":1,"RecipientEmail.email":1}}
]);
{ $project: {_id:1,ownerId:1, createdAt:1, confirmedAt:1,nameId:1, 'SenderEmail.email':1,'RecipientEmail.email':1}
}
];
//if(ourData.status==1) query = {"confirmedAt": { $exists: true, $ne: null }}

let optIns = OptIns.aggregate(pipeline);
Expand Down
8 changes: 6 additions & 2 deletions imports/modules/server/opt-ins/confirm.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,13 @@ const confirmOptIn = (request) => {
const decoded = decodeDoiHash({hash: request.hash});
const optIn = OptIns.findOne({_id: decoded.id});
if(optIn === undefined || optIn.confirmationToken !== decoded.token) throw "Invalid hash";
if(optIn.confirmationToken === decoded.token && optIn.confirmedAt != undefined){ // Opt-In was already confirmed on email click
logConfirm("OptIn already confirmed: ",optIn);
return decoded.redirect;
}
const confirmedAt = new Date();

OptIns.update({_id : optIn._id},{$set:{confirmedAt: confirmedAt, confirmedBy: ourRequest.host}, $unset: {confirmationToken: ""}});
//TODO after confirmation we deleted the confonfirmationtoken, now we keep it. can this be a security problem?
OptIns.update({_id : optIn._id},{$set:{confirmedAt: confirmedAt, confirmedBy: ourRequest.host}});

//TODO here find all DoichainEntries in the local database and blockchain with the same masterDoi
const entries = DoichainEntries.find({$or: [{name: optIn.nameId}, {masterDoi: optIn.nameId}]});
Expand Down
9 changes: 5 additions & 4 deletions imports/modules/server/opt-ins/verify.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,26 +30,27 @@ const verifyOptIn = (data) => {
const ourData = data;
VerifyOptInSchema.validate(ourData);
const entry = nameShow(VERIFY_CLIENT, ourData.name_id);
if(entry === undefined) return false;
if(entry === undefined) return {nameIdFound: "failed"};
const entryData = JSON.parse(entry.value);
const firstCheck = verifySignature({
data: ourData.recipient_mail+ourData.sender_mail,
signature: entryData.signature,
publicKey: ourData.recipient_public_key
})
});

if(!firstCheck) return {firstCheck: false};
if(!firstCheck) return {soiSignatureStatus: "failed"};
const parts = ourData.recipient_mail.split("@"); //TODO put this into getPublicKeyAndAddress
const domain = parts[parts.length-1];
const publicKeyAndAddress = getPublicKeyAndAddress({domain: domain});

if(!entryData.signature||!entryData.doiSignature)return {doiSignatureStatus: "missing"};
const secondCheck = verifySignature({
data: entryData.signature,
signature: entryData.doiSignature,
publicKey: publicKeyAndAddress.publicKey
})

if(!secondCheck) return {secondCheck: false};
if(!secondCheck) return {doiSignatureStatus: "failed"};
return true;
} catch (exception) {
throw new Meteor.Error('opt-ins.verify.exception', exception);
Expand Down
2 changes: 1 addition & 1 deletion private/version.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
"timestamp": "18-12-2018 10:46",
"version": "v0.0.7.7",
"commit": "c9f868ea85cbc4210e7d8a1a90e740518e5204af"
}
}
14 changes: 13 additions & 1 deletion server/test/1-basic-doi-test.1.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
createUser,
findUser,
exportOptIns,
requestConfirmVerifyBasicDoi, resetUsers, updateUser, deleteAllEmailsFromPop3
requestConfirmVerifyBasicDoi, resetUsers, updateUser, deleteAllEmailsFromPop3, confirmLink
} from "./test-api/test-api-on-dapp";
import {logBlockchain} from "../../imports/startup/server/log-configuration";
import {deleteOptInsFromAliceAndBob} from "./test-api/test-api-on-node";
Expand Down Expand Up @@ -94,6 +94,7 @@ if(Meteor.isAppTest) {
const exportedOptIns = exportOptIns(dappUrlAlice, logAdmin, true);
chai.expect(exportedOptIns).to.not.be.undefined;
chai.expect(exportedOptIns[0]).to.not.be.undefined;
chai.expect(exportedOptIns[0].RecipientEmail.email).to.be.equal(recipient_mail);
const exportedOptInsA = exportOptIns(dappUrlAlice, logUserA, true);
exportedOptInsA.forEach(element => {
chai.expect(element.ownerId).to.be.equal(logUserA.userId);
Expand Down Expand Up @@ -136,5 +137,16 @@ if(Meteor.isAppTest) {
requestConfirmVerifyBasicDoi(node_url_alice, rpcAuthAlice, dappUrlAlice, adLog, dappUrlBob, recipient_mail, sender_mail, {'city': 'Ekaterinburg'}, "bob@ci-doichain.org", "bob", true);
done();
});

it('should redirect if confirmation-link is clicked again',function(){
for (let index = 0; index < 3; index++) {
const recipient_mail = "bob@ci-doichain.org"; //please use this as standard to not confuse people!
const sender_mail = "alice_"+index+"@ci-doichain.org";
const dataLoginAlice = login(dappUrlAlice, dAppLogin, false); //log into dApp
let returnedData = requestConfirmVerifyBasicDoi(node_url_alice, rpcAuthAlice, dappUrlAlice, dataLoginAlice, dappUrlBob, recipient_mail, sender_mail, {'city': 'Ekaterinburg'}, "bob@ci-doichain.org", "bob", true);
chai.assert.equal(true,confirmLink(returnedData.confirmLink));
}

});
});
}
2 changes: 1 addition & 1 deletion server/test/2-basic-doi-test.2.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ if(Meteor.isAppTest) {
await new Promise(resolve => setTimeout(resolve, 2000));
}
}
})();
generatetoaddress(node_url_alice, rpcAuth, global.aliceAddress, 1, true);
verifyDOI(dappUrlAlice, dataLoginAlice, node_url_alice, rpcAuth, sender_mail, recipient_mail, nameId, log); //need to generate two blocks to make block visible on alice
testLogging('end of getNameIdOfRawTransaction returning nameId', nameId);
Expand All @@ -115,7 +116,6 @@ if(Meteor.isAppTest) {
testLogging('could not stop 3rd_node',);
}
done();
})();
//done();
}); //it
});
Expand Down
Loading

0 comments on commit f48084f

Please sign in to comment.