Skip to content

Commit e3d7a04

Browse files
Created the qucik_acg project
1 parent d10e0ee commit e3d7a04

File tree

4 files changed

+232
-8
lines changed

4 files changed

+232
-8
lines changed

config/appsettings.example.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
"documentation": null,
2525
"multiSourceChooser": false,
2626
"quickstart" : "{QUICKSTART_VALUE}",
27+
"quickACG" : "{QUICKACG_VALUE}",
2728
"roomsApiUrl": "https://demo.rooms.docusign.com",
2829
"clickAPIUrl": "https://demo.docusign.net/clickapi",
2930
"adminAPIUrl": "https://api-d.docusign.net/management",

lib/eSignature/controllers/eg001EmbeddedSigning.js

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -85,14 +85,25 @@ eg001EmbeddedSigning.getController = (req, res) => {
8585
// since they have not yet entered any information into the form.
8686
const tokenOK = req.dsAuth.checkToken();
8787
if (tokenOK) {
88-
res.render('pages/examples/eg001EmbeddedSigning', {
89-
eg: eg, csrfToken: req.csrfToken(),
90-
title: "Use embedded signing",
91-
sourceFile: path.basename(__filename),
92-
sourceUrl: 'https://github.com/docusign/code-examples-node/blob/master/eg001EmbeddedSigning.js',
93-
documentation: dsConfig.documentation + eg,
94-
showDoc: dsConfig.documentation
95-
});
88+
if (dsConfig.quickACG == "true") {
89+
res.render('pages/examples/quickEmbeddedSigning', {
90+
eg: eg, csrfToken: req.csrfToken(),
91+
title: "Use embedded signing",
92+
sourceFile: path.basename(__filename),
93+
sourceUrl: 'https://github.com/docusign/code-examples-node/blob/master/eg001EmbeddedSigning.js',
94+
documentation: dsConfig.documentation + eg,
95+
showDoc: dsConfig.documentation
96+
});
97+
} else {
98+
res.render('pages/examples/eg001EmbeddedSigning', {
99+
eg: eg, csrfToken: req.csrfToken(),
100+
title: "Use embedded signing",
101+
sourceFile: path.basename(__filename),
102+
sourceUrl: 'https://github.com/docusign/code-examples-node/blob/master/eg001EmbeddedSigning.js',
103+
documentation: dsConfig.documentation + eg,
104+
showDoc: dsConfig.documentation
105+
});
106+
}
96107
} else {
97108
// Save the current operation so it will be resumed after authentication
98109
req.dsAuth.setEg(req, eg);

quick_acg/index.js

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
#!/usr/bin/env node
2+
3+
const express = require('express');
4+
const session = require('express-session'); // https://github.com/expressjs/session
5+
const bodyParser = require('body-parser');
6+
const cookieParser = require('cookie-parser');
7+
const MemoryStore = require('memorystore')(session); // https://github.com/roccomuso/memorystore
8+
const path = require('path');
9+
const DSAuthCodeGrant = require('../lib/DSAuthCodeGrant');
10+
const passport = require('passport');
11+
const DocusignStrategy = require('passport-docusign');
12+
const docOptions = require('../config/documentOptions.json');
13+
const docNames = require('../config/documentNames.json');
14+
const dsConfig = require('../config/index.js').config;
15+
const commonControllers = require('../lib/commonControllers');
16+
const flash = require('express-flash');
17+
const helmet = require('helmet'); // https://expressjs.com/en/advanced/best-practice-security.html
18+
const moment = require('moment');
19+
const csrf = require('csurf'); // https://www.npmjs.com/package/csurf
20+
const examplesApi = require('../config/examplesApi.json');
21+
22+
const eg001 = require('../lib/eSignature/controllers/eg001EmbeddedSigning');
23+
24+
const PORT = process.env.PORT || 5000;
25+
const HOST = process.env.HOST || 'localhost';
26+
const max_session_min = 180;
27+
const csrfProtection = csrf({ cookie: true });
28+
29+
let hostUrl = 'http://' + HOST + ':' + PORT
30+
if (dsConfig.appUrl != '' && dsConfig.appUrl != '{APP_URL}') { hostUrl = dsConfig.appUrl }
31+
32+
let app = express()
33+
.use(helmet())
34+
.use(express.static(path.join(__dirname, 'public')))
35+
.use(cookieParser())
36+
.use(session({
37+
secret: dsConfig.sessionSecret,
38+
name: 'ds-launcher-session',
39+
cookie: { maxAge: max_session_min * 60000 },
40+
saveUninitialized: true,
41+
resave: true,
42+
store: new MemoryStore({
43+
checkPeriod: 86400000 // prune expired entries every 24h
44+
})
45+
}))
46+
.use(passport.initialize())
47+
.use(passport.session())
48+
.use(bodyParser.urlencoded({ extended: true }))
49+
.use(((req, res, next) => {
50+
res.locals.user = req.user;
51+
res.locals.session = req.session;
52+
res.locals.dsConfig = { ...dsConfig, docOptions: docOptions, docNames: docNames };
53+
res.locals.examplesApi = examplesApi
54+
res.locals.hostUrl = hostUrl; // Used by DSAuthCodeGrant#logout
55+
next()
56+
})) // Send user info to views
57+
.use(flash())
58+
.set('views', path.join(__dirname, '../views'))
59+
.set('view engine', 'ejs')
60+
// Add an instance of DSAuthCodeGrant to req
61+
.use((req, res, next) => {
62+
req.dsAuthCodeGrant = new DSAuthCodeGrant(req);
63+
req.dsAuth = req.dsAuthCodeGrant;
64+
next()
65+
})
66+
.use(csrfProtection) // CSRF protection for the following routes
67+
// Routes
68+
.get('/', redirectEg001)
69+
.get('/eg001', eg001.getController)
70+
.post('/eg001', eg001.createController)
71+
.get('/ds/mustAuthenticate', redirectLogin)
72+
.get('/ds/login', commonControllers.login)
73+
.get('/ds/logout', commonControllers.logout)
74+
.get('/ds/logoutCallback', commonControllers.logoutCallback)
75+
.get('/ds-return', redirectReturn)
76+
.get('/ds/callback', [dsLoginCB1, dsLoginCB2]) // OAuth callbacks. See below
77+
;
78+
79+
function redirectEg001(req, res) { return res.redirect('/eg001'); }
80+
function redirectLogin(req, res) { return res.redirect('/ds/login'); }
81+
function redirectReturn(req, res) { return res.redirect('/eg001'); }
82+
function dsLoginCB1(req, res, next) { req.dsAuthCodeGrant.oauth_callback1(req, res, next) }
83+
function dsLoginCB2(req, res, next) { req.dsAuthCodeGrant.oauth_callback2(req, res, next) }
84+
85+
if (dsConfig.dsClientId && dsConfig.dsClientId !== '{CLIENT_ID}' &&
86+
dsConfig.dsClientSecret && dsConfig.dsClientSecret !== '{CLIENT_SECRET}') {
87+
app.listen(PORT)
88+
console.log(`Listening on ${PORT}`);
89+
console.log(`Ready! Open ${hostUrl}`);
90+
} else {
91+
console.log(`PROBLEM: You need to set the clientId (Integrator Key), and perhaps other settings as well.
92+
You can set them in the configuration file config/appsettings.json or set environment variables.\n`);
93+
process.exit(); // We're not using exit code of 1 to avoid extraneous npm messages.
94+
}
95+
96+
// Passport session setup.
97+
// To support persistent login sessions, Passport needs to be able to
98+
// serialize users into and deserialize users out of the session. Typically,
99+
// this will be as simple as storing the user ID when serializing, and finding
100+
// the user by ID when deserializing. However, since this example does not
101+
// have a database of user records, the complete DocuSign profile is serialized
102+
// and deserialized.
103+
passport.serializeUser(function (user, done) { done(null, user) });
104+
passport.deserializeUser(function (obj, done) { done(null, obj) });
105+
106+
let scope = ["signature"];
107+
108+
// Configure passport for DocusignStrategy
109+
let docusignStrategy = new DocusignStrategy({
110+
production: dsConfig.production,
111+
clientID: dsConfig.dsClientId,
112+
scope: scope.join(" "),
113+
clientSecret: dsConfig.dsClientSecret,
114+
callbackURL: hostUrl + '/ds/callback',
115+
state: true // automatic CSRF protection.
116+
// See https://github.com/jaredhanson/passport-oauth2/blob/master/lib/state/session.js
117+
},
118+
function _processDsResult(accessToken, refreshToken, params, profile, done) {
119+
// The params arg will be passed additional parameters of the grant.
120+
// See https://github.com/jaredhanson/passport-oauth2/pull/84
121+
//
122+
// Here we're just assigning the tokens to the account object
123+
// We store the data in DSAuthCodeGrant.getDefaultAccountInfo
124+
let user = profile;
125+
user.accessToken = accessToken;
126+
user.refreshToken = refreshToken;
127+
user.expiresIn = params.expires_in;
128+
user.tokenExpirationTimestamp = moment().add(user.expiresIn, 's'); // The dateTime when the access token will expire
129+
return done(null, user);
130+
}
131+
);
132+
133+
/**
134+
* The DocuSign OAuth default is to allow silent authentication.
135+
* An additional OAuth query parameter is used to not allow silent authentication
136+
*/
137+
if (!dsConfig.allowSilentAuthentication) {
138+
// See https://stackoverflow.com/a/32877712/64904
139+
docusignStrategy.authorizationParams = function (options) {
140+
return { prompt: 'login' };
141+
}
142+
}
143+
passport.use(docusignStrategy);
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
6+
<meta name="description" content="">
7+
<meta name="author" content="">
8+
<link rel="icon" href="assets/favicon.ico">
9+
10+
<title><%= title %></title>
11+
12+
<!-- Bootstrap core CSS -->
13+
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
14+
<!-- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.13.1/styles/default.min.css"> -->
15+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.13.1/styles/darcula.min.css">
16+
<!-- Custom styles for this template -->
17+
<link href="/assets/css.css" rel="stylesheet">
18+
</head>
19+
20+
<body>
21+
22+
<nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top">
23+
<a class="navbar-brand" target="_blank" href="https://developers.docusign.com">DocuSign Developer</a>
24+
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsExampleDefault" aria-controls="navbarsExampleDefault" aria-expanded="false" aria-label="Toggle navigation">
25+
<span class="navbar-toggler-icon"></span>
26+
</button>
27+
28+
<div class="collapse navbar-collapse" id="navbarsExampleDefault">
29+
<ul class="navbar-nav mr-auto"></ul>
30+
31+
<% if (locals.user) { %>
32+
<span class="navbar-text">
33+
Welcome <%= locals.user.name %>
34+
</span>
35+
<% } %>
36+
37+
</div>
38+
</nav>
39+
40+
<div class="container" style="margin-top: 100px">
41+
42+
<h4>Use embedded signing</h4>
43+
<p>This example sends an envelope, and then uses embedded signing for the first signer.</p>
44+
<p>Embedded signing provides a smoother user experience for the signer: the DocuSign signing is initiated from your website.</p>
45+
46+
<p>API methods used:
47+
<a target ='_blank' href="https://developers.docusign.com/docs/esign-rest-api/reference/envelopes/envelopes/create/">Envelopes::create</a> and
48+
<a target ='_blank' href="https://developers.docusign.com/docs/esign-rest-api/reference/envelopes/envelopeviews/createrecipient/">EnvelopeViews::createRecipient</a>.
49+
</p>
50+
<% include ../../partials/gitSource %>
51+
<form class="eg" action="" method="post" data-busy="form">
52+
<div class="form-group">
53+
<label for="signerEmail">Signer Email</label>
54+
<input type="email" class="form-control" id="signerEmail" name="signerEmail"
55+
aria-describedby="emailHelp" placeholder="pat@example.com" required
56+
value="<%= locals.dsConfig.signerEmail %>">
57+
<small id="emailHelp" class="form-text text-muted">We'll never share your email with anyone else.</small>
58+
</div>
59+
<div class="form-group">
60+
<label for="signerName">Signer Name</label>
61+
<input type="text" class="form-control" id="signerName" placeholder="Pat Johnson" name="signerName"
62+
value="<%= locals.dsConfig.signerName %>" required>
63+
</div>
64+
<input type="hidden" name="_csrf" value="<%- csrfToken %>">
65+
<button type="submit" class="btn btn-docu">Submit</button>
66+
</form>
67+
</div>
68+
</body>
69+
</html>

0 commit comments

Comments
 (0)