I have a login service with discord Oauth2.
After the user authorize discord, they are redirected to home page.
my login service is like this:
login() {
this.commonService.showLoadingOverlay();
return this.http.get('http://localhost:3000/auth/login/').subscribe((data: any) => {
const token = data.token;
this.token = token;
if (token) {
this.userInfo = data.user;
console.log(this.userInfo);
this.userId = data.user.user_id;
this.discordId = data.user.discord_id;
this.authStatusListener.next(true);
this.isAuthenticated = true;
const expiresInDuration = data.expiresIn;
const now = new Date();
const expirationDate = new Date(now.getTime() + expiresInDuration * 1000);
this.saveAuthData(token, expirationDate, this.userId, this.userInfo);
this.setAuthTimer(expiresInDuration);
this.commonService.hideLoadingOverlay();
this.router.navigate(['/']);
}
}, error => {
this.commonService.hideLoadingOverlay();
this.router.navigate(['/'])
const message = 'Not logged in...'
this.commonService.showErrorMessage(message);
}
)
}
Following a guide I was told to add this to save in local storage:
private getAuthData() {
const token = localStorage.getItem("token");
const expirationDate = localStorage.getItem("expiration");
const userId = localStorage.getItem("userId");
const userInfo = localStorage.getItem("userInfo");
if (!token || !expirationDate) {
return;
}
return {
token: token,
expirationDate: new Date(expirationDate),
userId: userId,
userInfo: userInfo
}
}
autoAuthUser() {
const authInformation = this.getAuthData();
if (!authInformation) {
return;
}
const now = new Date();
const expiresIn = authInformation.expirationDate.getTime() - now.getTime();
if (expiresIn > 0) {
this.token = authInformation.token;
this.isAuthenticated = true;
this.userId = authInformation.userId;
this.userInfo = authInformation.userInfo;
this.setAuthTimer(expiresIn / 1000);
this.authStatusListener.next(true);
}
}
I also have this to get the user info:
getUserInfo() {
return this.userInfo;
}
getUserId() {
return this.userId;
}
in my sidenav component I am calling user info like this:
if(this.currentUser) {
this.userId = this.authService.getUserId();
console.log(this.userId);
this.userInfo = this.authService.getUserInfo();
console.log('user:')
console.log(this.userInfo);
}
user ID is comming fine, but the user info object is coming as [Object Object], I have also tried to console.log userInfo.user_id
the data should be like this:
{user_id: "13", discord_id: "123456xxxx", username: null}
any ideas?
Thanks :)
You can't write an actual object into local storage with localStorage.setItem and read it with localStorage.getItem. You have to stringify before you write it there and parse after you read it.
The result of writing an actual object into local storage with localStorage.setItem is that the string "[object Object]" is stored instead of the object. In
const userInfo = localStorage.getItem("userInfo");
you are reading the string from local storage and writing it into userInfo.
You should
const userInfo = JSON.parse(localStorage.getItem("userInfo"));
and
const userInfo = {user_id: "13", discord_id: "123456xxxx", username: null};
localStorage.setItem("userInfo", JSON.stringify(userInfo));
You can see the problem when you open the local storage in your browser and check the value for userInfo. It's not
{user_id: "13", discord_id: "123456xxxx", username: null}
but
[object Object]
Related
my code:
const { Api, TelegramClient } = require("telegram");
const { StringSession } = require("telegram/sessions");
const { Logger } = require("telegram/extensions");
const apiId = 22;
const apiHash = "333333";
const phoneNumber = "9996627328";
const phoneCode = "22222";
const createClient = async (stringSession) => {
const session = new StringSession(stringSession);
const options = { connectionRetries: 5, baseLogger: new Logger("debug") };
const client = new TelegramClient(session, apiId, apiHash, options);
client.session.setDC(2, "149.154.167.40", 443);
await client.connect();
return client;
};
const getLoginCodeCommand = (phoneNumber) => {
const settings = new Api.CodeSettings();
const args = { phoneNumber, apiId, apiHash, settings };
return new Api.auth.SendCode(args);
};
(async () => {
const client = await createClient("");
const response = await client.invoke(getLoginCodeCommand(phoneNumber));
console.log('responseļ¼', response);
const { phoneCodeHash } = response;
const result22 = await client.invoke(
new Api.auth.SignUp({
phoneNumber: phoneNumber,
phoneCodeHash: phoneCodeHash,
firstName: "liu",
lastName: "some",
})
);
console.log("RESULT22", result22);
})();
response:
/Users/xizao/work/fm/project/telegram/node_modules/telegram/errors/index.js:28
return new RPCBaseErrors_1.RPCError(rpcError.errorMessage, request, rpcError.errorCode);
^
RPCError: 400: PHONE_CODE_INVALID (caused by auth.SignUp)
at RPCMessageToError (/Users/xizao/work/fm/project/telegram/node_modules/telegram/errors/index.js:28:12)
at MTProtoSender._handleRPCResult (/Users/xizao/work/fm/project/telegram/node_modules/telegram/network/MTProtoSender.js:517:58)
at MTProtoSender._processMessage (/Users/xizao/work/fm/project/telegram/node_modules/telegram/network/MTProtoSender.js:442:15)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async MTProtoSender._recvLoop (/Users/xizao/work/fm/project/telegram/node_modules/telegram/network/MTProtoSender.js:418:17) {
code: 400,
errorMessage: 'PHONE_CODE_INVALID'
}
No matter how you adjust it, the phone code is always invalid
The correct result should be direct registration success.
I haven't been able to find the problem because of what? Please help me to see why?
doc link: https://gram.js.org/tl/auth/SignUp#authsignup
When I call createClickwrap method, I got 404 error Not Found. If I run this method through Quickstart generated demo project, I don't get this error. However, if I run it through my project I get the error. If I debug the demo app and my app, the functions parameters are the same.
This is the code in my app:
docusign controller:
const docuSignService = require('./docusign_esign_service');
const demoDocumentsPath = path.resolve(__dirname, '../demo_documents');
const { createClickwrap } = require('./createClickWrap');
async getDocusignRecieptService() {
const authResponse = await docuSignService.authenticate();
if (authResponse) {
const docTermsPdf = 'Term_Of_Service.pdf';
const docFile = path.resolve(demoDocumentsPath, docTermsPdf);
const { basePath, accessToken, apiAccountId } = authResponse;
const { clickwrapId } = await createClickwrap({ docFile, basePath, accessToken, accountId: apiAccountId });
const res = await activateClickwrap({ clickwrapId, basePath, accessToken, accountId: apiAccountId });
console.log({ res });
}
}
docuSignService.js
const SCOPES = ['signature', 'impersonation', 'openid', 'click.manage', 'click.send'];
const fs = require('fs');
const docusign = require('docusign-esign');
class DocusingService {
async authenticate() {
const jwtLifeSec = 10 * 60, // requested lifetime for the JWT is 10 min
dsApi = new docusign.ApiClient();
dsApi.setOAuthBasePath(process.env.dsOauthServer.replace('https://', '')); // it should be domain only.
let rsaKey = fs.readFileSync(process.env.privateKeyLocation);
try {
const results = await dsApi.requestJWTUserToken(
process.env.dsJWTClientId,
process.env.impersonatedUserGuid,
SCOPES,
rsaKey,
jwtLifeSec
);
const accessToken = results.body.access_token;
// get user info
const userInfoResults = await dsApi.getUserInfo(accessToken);
// use the default account
let userInfo = userInfoResults.accounts.find((account) => account.isDefault === 'true');
return {
accessToken: results.body.access_token,
apiAccountId: userInfo.accountId,
basePath: `${userInfo.baseUri}/restapi`
};
} catch (e) {
let body = e.response && e.response.body;
// Determine the source of the error
if (body) {
// The user needs to grant consent
if (body.error && body.error === 'consent_required') {
if (this.getConsent()) {
return this.authenticate();
}
} else {
// Consent has been granted. Show status code for DocuSign API error
this._debug_log(`\nAPI problem: Status code ${e.response.status}, message body:
${JSON.stringify(body, null, 4)}\n\n`);
}
}
}
}
getConsent() {
var urlScopes = SCOPES.join('+');
// Construct consent URL
var redirectUri = 'https://developers.docusign.com/platform/auth/consent';
var consentUrl =
`${process.env.dsOauthServer}/oauth/auth?response_type=code&` +
`scope=${urlScopes}&client_id=${process.env.dsJWTClientId}&` +
`redirect_uri=${redirectUri}`;
throw new Error(`Open the following URL in your browser to grant consent to the application: ${consentUrl}`);
}
getArgs(apiAccountId, accessToken, basePath, signerEmail, signerName, id, agreementData, redirect_uri) {
const envelopeArgs = {
signerEmail: signerEmail,
signerName: signerName,
status: 'sent',
signerClientId: id,
dsReturnUrl: redirect_uri,
agreement: agreementData
};
const args = {
accessToken: accessToken,
basePath: basePath,
accountId: apiAccountId,
envelopeArgs: envelopeArgs
};
return args;
}
}
module.exports = new DocusingService();
createClickWrap.js
const createClickwrap = async ({ docFile, clickwrapName = 'clickwrapName', basePath, accessToken, accountId }) => {
// Step 3. Construct the request Body
// Create display settings model
const displaySettings = docusignClick.DisplaySettings.constructFromObject({
consentButtonText: 'I Agree',
displayName: 'Terms of Service',
downloadable: true,
format: 'modal',
hasAccept: true,
mustRead: true,
requireAccept: true,
documentDisplay: 'document'
});
// Create document model
// Read and encode file. Put encoded value to Document entity.
// The reads could raise an exception if the file is not available!
const documentPdfExample = fs.readFileSync(docFile);
const encodedExampleDocument = Buffer.from(documentPdfExample).toString('base64');
const document = docusignClick.Document.constructFromObject({
documentBase64: encodedExampleDocument,
documentName: 'Terms of Service',
fileExtension: 'pdf',
order: 0
});
// Create clickwrapRequest model
const clickwrapRequest = docusignClick.ClickwrapRequest.constructFromObject({
displaySettings,
documents: [document],
name: clickwrapName,
requireReacceptance: true
});
// Step 4. Call the Click API
const dsApiClient = new docusignClick.ApiClient();
dsApiClient.setBasePath(basePath);
dsApiClient.addDefaultHeader('Authorization', 'Bearer ' + accessToken);
const accountApi = new docusignClick.AccountsApi(dsApiClient);
// Create a clickwrap
let result = null;
try {
result = await accountApi.createClickwrap(accountId, {
clickwrapRequest
});
} catch (e) {
debugger;
console.log(e);
}
debugger;
console.log(`Clickwrap was created. ClickwrapId ${result.clickwrapId}`);
return result;
};
module.exports = { createClickwrap };
Parameters look like this in the demo app and it works:
and these are the parameters in my app:
The first parameter accountId is the same. Why I am getting this issue in my app if function gets the same parameters?
"Error: Not Found
at Request.callback (/Users/and/test/node_modules/docusign-click/node_modules/superagent/lib/node/index.js:696:15)
at IncomingMessage.<anonymous> (/Users/and/test/node_modules/docusign-click/node_modules/superagent/lib/node/index.js:906:18)
at IncomingMessage.emit (node:events:539:35)
at IncomingMessage.emit (node:domain:475:12)
at endReadableNT (node:internal/streams/readable:1345:12)
at processTicksAndRejections (node:internal/process/task_queues:83:21)"
Thanks to pointing out in the comments, when I changed basePath ${userInfo.baseUri}/restapi to ${userInfo.baseUri}/clickapi, it works now.
I have a node.js application where I'm using the sign in functionality.
I'm facing an issue; that is, when I try to sign in, sometimes the request gets stuck. It won't return anything until I refresh the node.js server. Can anybody take a look at the code and help me out what am I doing wrong here?
Here is my Controller function
export const authenticate = async (
req: Request,
res: Response
): Promise<void> => {
try {
console.log("Login")
const result: DataObject = await model.authenticate(
req.body.username,
req.body.password
)
const { status, data } = result
res.status(status)
if(status==200) {
console.log(status)
const u : User = data as User;
const token = jwt.sign({ id: u.id }, process.env.JWT_SECRET as string)
res.json({token: token})
}
else {
res.json(data)
}
} catch (error) {
res.status(NOT_FOUND)
res.json(error)
}
}
And my Model method.
async authenticate(username: string, password: string): Promise<DataObject> {
try {
const sql =
"SELECT * FROM users WHERE username=$1"
const conn: PoolClient = await Client.connect()
const result: QueryResult<User> = await conn.query(sql, [username])
const { rows } = result
if (rows.length > 0) {
const user: User = rows[0]
const pepper: string = process.env.PASSWORD_HASH as string
const pepperedPass = password + pepper;
const validPass : boolean = bcrypt.compareSync(pepperedPass, user.password_digest);
if (validPass) {
const result: DataObject = {
status: OK,
data: user,
}
return result
}
else {
const passErr: DataObject = {
status: NOT_FOUND,
data: "Incorrect Password",
}
return passErr
}
}
const userErr: DataObject = {
status: NOT_FOUND,
data: "No User found with this Username",
}
return userErr
} catch (error) {
const userErr: DataObject = {
status: NOT_FOUND,
data: "No User found with this Username",
}
return userErr
throw new Error(`Not found, ${error}`)
}
}
I have tried res._destroy, res.set("Connection", "close"); but the issue persists.
Any suggestion/solution is appreciated.
Thank you.
I am using node to list all users from domain. I had created service account with domain wide delegation.
The domain admin gave access to the service account to required scopes.
Code:
const { JWT } = require('google-auth-library');
const {google, chat_v1} = require('googleapis');
const keys = require('./keys.json')
async function main() {
const client = new JWT(keys.client_email, keys, keys.private_key,
['https://www.googleapis.com/auth/admin.directory.user',
'https://www.googleapis.com/auth/admin.directory.user.readonly',
'https://www.googleapis.com/auth/cloud-platform'],
"admin#domain.com"
);
await client.authorize();
const service = google.admin("directory_v1");
service.users.list({
domain: "domain.com",
maxResults: "10",
orderBy: "email",
}, (err, res) => {
if (err) return console.error('The API returned an error:', err.message);
const users = res.data.users;
if (users.length) {
console.log('Users:');
users.forEach((user) => {
console.log(`${user.primaryEmail} (${user.name.fullName})`);
});
} else {
console.log('No users found.');
}
});
}
main();
but only thing I recive is:
The API returned an error: Login Required.
also enabled admin sdk api for this service account
any idea why this is happening?
I'm not sure if JWT is the correct way, but this is how I do it.
const google = require("googleapis").google;
const SRVC_ACCOUNT_CREDS = require('./keys.json');
const getClient = async (scopes: string[], user: string)=>{
const auth = new google.auth.GoogleAuth({
credentials: SRVC_ACCOUNT_CREDS,
scopes: scopes
});
const client = await auth.getClient();
client.subject = user;
return client;
};
const listUsers = async (query = "", limit = 500, pageToken = null, user, fields, getAll = false)=>{
const scopes = ["https://www.googleapis.com/auth/admin.directory.user"];
const client = await getClient(scopes, user);
const service = google.admin({version: "directory_v1", auth: client});
const result = {
users: [],
nextPageToken: ""
};
if(!fields) {
fields = "users(name.fullName,primaryEmail,organizations(department,primary,title),thumbnailPhotoUrl),nextPageToken";
}
do{
const request = await service.users.list({
customer: "my_customer",
fields: fields,
orderBy: "givenName",
maxResults: limit,
pageToken: pageToken,
query: query,
viewType: "admin_view"
});
pageToken = getAll ? request.data.nextPageToken : null;
const users = request.data.users;
if(users && users.length){
result.users.push(...users);
result.nextPageToken = request.data.nextPageToken;
}
} while(pageToken);
return result;
};
I'm trying to send an envelope from a template in a webhook listener. I'm using node.js with .mjs files. When I send the envelope via the docusign dashboard it has the tabs - full name, SSN, phone number, address. But when the API sends the envelope, it has those words but no fields next to them. This is a problem because we need that info and there's nowhere for the signer to input it. What could be causing the tabs to not appear when the envelope is sent from the api?
Here's the code to create an envelope and use a template (based off docs):
import docusign from 'docusign-esign';
export function makeEnvelope(args){
// Create the envelope definition
let env = new docusign.EnvelopeDefinition();
env.templateId = args.templateId;
// Create template role elements to connect the signer and cc recipients
// to the template
// We're setting the parameters via the object creation
let signer1 = docusign.TemplateRole.constructFromObject({
email: args.signerEmail,
name: args.signerName,
roleName: 'signer'});
// Create a cc template role.
// We're setting the parameters via setters
let cc1 = new docusign.TemplateRole();
cc1.email = args.ccEmail;
cc1.name = args.ccName;
cc1.roleName = 'cc';
// Add the TemplateRole objects to the envelope object
env.templateRoles = [signer1, cc1];
env.status = 'sent'; // We want the envelope to be sent
return env;
}
export async function useTemplate(args) {
let dsApiClient = new docusign.ApiClient();
dsApiClient.setBasePath(args.basePath);
dsApiClient.addDefaultHeader('Authorization', 'Bearer ' + args.accessToken);
let envelopesApi = new docusign.EnvelopesApi(dsApiClient);
// Make the envelope request body
let envelope = makeEnvelope(args.envelopeArgs);
// Call Envelopes::create API method
// Exceptions will be caught by the calling function
let results = await envelopesApi.createEnvelope(
args.accountId, {envelopeDefinition: envelope});
return results;
};
Here's the code for the webhook listener where I call useTemplate (please excuse the commented out code and the console logs - I'm still in the midst of figuring it all out):
import express from 'express';
import { useTemplate } from '../request/docusign/docusign-methods.mjs';
import opportunities from '../request/prosperworks/opportunities.mjs';
import people from '../request/prosperworks/people.js';
import customFields from '../request/prosperworks/custom-fields.mjs';
import { findTemplateIdByCohortName } from '../request/docusign/templates.mjs';
import { findSentEnvelopesByStudentEmail, voidEnvelope, findTemplateFromEnvelopeTemplateUri } from '../request/docusign/envelopes.mjs';
import { createJWT, getAccessTokenFromJWT } from '../request/docusign/token.mjs';
import { getAccessToken } from '../request/quickbooks/tokens.mjs';
import { findCustomerByEmail } from '../request/quickbooks/customer.mjs';
import { createCustomer } from '../request/quickbooks/customer.mjs';
import { createInvoice, sendInvoice } from '../request/quickbooks/invoice.mjs';
import { findItemByName } from '../request/quickbooks/item.mjs';
const router = express.Router();
export default router
.post('/copper/opportunity/updated', express.json(), async (req, res, next) => {
const { body } = req;
console.log('webhook received', body);
if(!Object.keys(body.updated_attributes).length) return res.send('irrelevant webhook');
const cohortChanged = !!body.updated_attributes?.custom_fields?.['94620']
console.log('cohort changed?', cohortChanged);
const interviewScheduledToAccepted = !!(body.updated_attributes?.stage?.[0] === 'Interview Scheduled' && body.updated_attributes?.stage?.[1] === 'Accepted')
console.log('interview scheduled to accepted?', interviewScheduledToAccepted);
const fullConditional = cohortChanged || interviewScheduledToAccepted;
console.log('full conditional', fullConditional);
if(fullConditional) {
try {
const jwt = await createJWT();
const docusign_access_token = await getAccessTokenFromJWT(jwt);
const opportunity = await opportunities.get(body.ids[0]);
const cohortId = opportunity?.custom_fields?.find(field => field.custom_field_definition_id === 94620)?.value || null;
const cohortName = customFields.getCohortNameById(cohortId);
console.log('cohort name', cohortName);
const templateId = await findTemplateIdByCohortName(cohortName, docusign_access_token);
const person = await people.findById(opportunity.primary_contact_id);
const email = person.emails[0].email;
console.log('email', email);
const { name } = person;
// if(interviewScheduledToAccepted) {
// const quickbooks_access_token = await getAccessToken();
// let customer = await findCustomerByEmail(email, quickbooks_access_token);
// if(customer === null) {
// customer = await createCustomer(cohortName, person, quickbooks_access_token);
// };
// console.log('customer', customer);
// const product = await findItemByName('Deposit', quickbooks_access_token);
// const invoice = await createInvoice(customer, product, cohortName, quickbooks_access_token);
// const sentInvoice = await sendInvoice(email, invoice.Invoice.Id, quickbooks_access_token)
// console.log('sent invoice', sentInvoice);
// }
const sentEnvelopes = await findSentEnvelopesByStudentEmail(email, docusign_access_token);
await Promise.all(
sentEnvelopes.filter(envelope => {
return envelope.emailSubject.includes('Enrollment Agreement');
})
.map(envelope => {
if(envelope.status === 'sent') return voidEnvelope(envelope.envelopeId, docusign_access_token);
})
);
const sentEnvelopesTemplates = await Promise.all(
sentEnvelopes
.filter(envelope => {
return envelope.status !== 'voided'
})
.map(envelope => {
return findTemplateFromEnvelopeTemplateUri(envelope.templatesUri, docusign_access_token);
})
);
const templateAlreadyUsedCheck = sentEnvelopesTemplates.reduce((outerAcc, templateArr) => {
if(templateArr.reduce((innerAcc, template) => {
if(template.templateId === templateId) innerAcc=true;
return innerAcc;
}, false)) {
outerAcc=true;
}
return outerAcc;
}, false);
if(templateAlreadyUsedCheck) return res.send('envelope already sent');
const envelopeArgs = {
templateId: templateId,
signerEmail: email,
signerName: name
}
console.log(envelopeArgs);
const envelope = await useTemplate({
basePath: process.env.DOCUSIGN_BASE_PATH,
accessToken: docusign_access_token,
accountId: process.env.DOCUSIGN_ACCOUNT_ID,
envelopeArgs
});
return res.send(envelope);
}
catch(err) {
console.log(err.message);
next(err);
}
} else {
return res.send('irrelevant webhook');
}
});
Inbar Gazit figured it out - it turns out I had student as the role name in the template and signer as the role name in my code so that's why it wasn't working.