How to get department and manager's email through google admin sdk? - google-apps-script

I am calling google admin directory api to get user through email and then storing the organizations return in org.
var user = AdminDirectory.Users.get(bmail);
org = user.organizations;
Output
[ { customType: '',
title: 'PM',
department: 'BIT',
primary: true,
description: 'Permanent' } ]
How can i get only department in org? I've tried to use get.child(element) to get the department however not successful.
How can i get only manager's email? I've read the Rest Resource Users but there is no information related to manager's email.
Any reference or help will be much appreciated.
Thank you

You already have the User object, so if you want to read the department property you only have to navigate its tree. See the example below:
function myFunction() {
var user = AdminDirectory.Users.get(bmail);
org = user['organizations'][0]['department'];
}
Now to answer your second question you could use the relations field to keep track of the user's managers. Feel free to drop a comment if you need further clarifications.

Related

How can I get UserPool details by IdentityPool/UserPool id (sub)

Is there a way to get user details (profile attributes etc) if I have IdentityPool or UserPool ID (sub) of a user with AWS SDK?
The use case is that I'm saving some information submitted by a user in a DB with a key equal to user ID (sub). So, when I'm reading it from the DB, I want to restore back some user info from my pool for my app UI.
I found a similar question (Getting cognito user pool username from cognito identity pool identityId), but it seems, the answer given is focused around serverless deployment, and still has some gaps.
Thanks in advance
Since you have the user's sub, you can use AdminGetUser. It returns the UserAttributes in the pool.
I think I found a solution, it was on the surface actually.
Having user pool id one can use ListUsers call with filter sub = \"${userId}\". The client to be used is CognitoIdentityProviderClient, if JS is used.
const client = new CognitoIdentityProviderClient({
region: REGION,
credentials: fromCognitoIdentityPool({
client: new CognitoIdentityClient({ region: REGION }),
logins: {
[PROVIDER_ID]: token
},
identityPoolId: ID_POOL_ID
})
});
const filter = `sub = \"${userPoolId}\"`;
const resp = await client.send(new ListUsersCommand({
UserPoolId: USER_POOL_ID,
Filter: filter,
Limit: 1
}));
Of course AdminGetUser can be used as well, as Ulas Keles mentioned above, if it's applicable

How to add member with name into group from Google Apps Script?

I want to add members to Google group using AdminDirectory.Members.insert.
This is my code:
function addGroupMember() {
var member = {
name: {
givenName: 'Jhon',
familyName: 'Doe'
},
email: 'mail#example.com',
role: 'MEMBER'
};
var newMember=AdminDirectory.Members.insert(member, 'group_email#example.com');
}
The members is created into Group Members of Google Workspace, but without name, as you can see below:
There is one way to change Member by John Doe?
NOTE: The email domain is external, is not the same of the organization.
You may want to take a deeper look at the documentation.
From the Member overview:
A Google Groups member can be a user or another group.
Also you can see that the Member resource has no attribute name so it's indeed impossible to assign it a name before creating the User resource.
What you can do right now is creating an User through the users.insert request. After that store the id of said user and insert it into a group with members.insert.
And of course if you have already created a bunch of users without specifying the names you can update them.

Sequelize.js Node.js: How to Pass Already Created Object to Create Many-to-Many relationship?

From this post: Node.js / Sequelize.js / Express.js - How to insert into many-to-many association? (sync/async?)
The answer show only when you create Individual and Email, however, I want to create an Individual with an already created email.
Original answer to correctly create Individual and Email after one another:
models.Individual.create({
name: "Test"
}).then(function(createdIndividual) { // note the argument
models.Email.create({
address: "test#gmail.com"
}).then(function(createdEmail) { // note the argument
createdIndividual.addEmail(createdEmail)
.then(function(addedEmail) { // note th-- well you get the idea :)
console.log("Success");
});
})
});
To create an individual with an already created email, I modified into this:
models.Individual.create({
name: "Test"
}).then(function(createdIndividual) { // note the argument
//This email id exists in the Email table.
var email = {
id: 1
}
createdIndividual.addEmail(email)
.then(function(addedEmail) {
console.log("Success");
});
});
Then I got this error:
Unhandled rejection TypeError: val.replace is not a function
at Object.SqlString.escape (/Users/Roller/Working/Web/ponds_web/node_modules/sequelize/lib/sql-string.js:63:15)
at Object.QueryGenerator.escape (/Users/Roller/Working/Web/ponds_web/node_modules/sequelize/lib/dialects/abstract/query-generator.js:977:22)
at /Users/Roller/Working/Web/ponds_web/node_modules/sequelize/lib/dialects/abstract/query-generator.js:2203:23
at Array.map (native)
at Object.QueryGenerator.whereItemQuery (/Users/Roller/Working/Web/ponds_web/node_modules/sequelize/lib/dialects/abstract/query-generator.js:2202:49)
at /Users/Roller/Working/Web/ponds_web/node_modules/sequelize/lib/dialects/abstract/query-generator.js:1903:25
at /Users/Roller/Working/Web/ponds_web/node_modules/sequelize/node_modules/lodash/lodash.js:4389:15
at baseForOwn (/Users/Roller/Working/Web/ponds_web/node_modules/sequelize/node_modules/lodash/lodash.js:2652:24)
at Function.forOwn (/Users/Roller/Working/Web/ponds_web/node_modules/sequelize/node_modules/lodash/lodash.js:12254:24)
at Object.QueryGenerator.whereItemsQuery (/Users/Roller/Working/Web/ponds_web/node_modules/sequelize/lib/dialects/abstract/query-generator.js:1902:9)
at Object.QueryGenerator.getWhereConditions (/Users/Roller/Working/Web/ponds_web/node_modules/sequelize/lib/dialects/abstract/query-generator.js:2337:19)
at Object.QueryGenerator.selectQuery (/Users/Roller/Working/Web/ponds_web/node_modules/sequelize/lib/dialects/abstract/query-generator.js:1451:28)
at QueryInterface.select (/Users/Roller/Working/Web/ponds_web/node_modules/sequelize/lib/query-interface.js:669:25)
at .<anonymous> (/Users/Roller/Working/Web/ponds_web/node_modules/sequelize/lib/model.js:1390:32)
at tryCatcher (/Users/Roller/Working/Web/ponds_web/node_modules/bluebird/js/release/util.js:16:23)
at Promise._settlePromiseFromHandler (/Users/Roller/Working/Web/ponds_web/node_modules/bluebird/js/release/promise.js:504:31)
I think this error because my email object is not a Sequelize object.
Questions in mind:
Should we convert the email object into a Sequalize object by query from Email models? Will it work?
What's the better way to convert that object into Sequalize, as clean code and performance are concerned?
What if I have multiple emails to be added into Individual_Email when creating a new Product? Like more than 1 email ids.
Please help to advice. Thanks.
You are correct, the problem is that email is not a sequelize object. It would work if you retrieve it from database before adding it. On the other hand sequelize allows you to set childs by id. So you can do something like this:
models.Individual.create({
name: "Test"
}).then(function(createdIndividual) {
createdIndividual.setEmails([emailIds]) //emails id array
.then(function() {
console.log("Success");
});
});

Row level permissions in sails.js

I need row-level permissions in sails. I already looked at this and at other threads, but everybody says to just use policies.
But what I need isn't just limiting the ability to do e.g. find/update all elements of a table but to have permissions per database row that consider associations for permissions.
It would be great if the permissions support blueprints like the ember data adapter, nested create/update/find (with populate) and sockets.
So for example:
GET /:model/:id
should return and populate with such entries where certain associated conditions are met.
So for example, we have 4 models:
User (columns: id, name, email, pwd_hash, ...)
Project (columns: id, client, name, ...)
UserAssignment (columns: id, user, project, user_perms, ...)
Client (columns: id, name, ...)
User and Project are linked through UserAssignment - an advanced MM-Table. (Users may have special user_perms to different projects, such as read,write,manage). And a Project always has one Client.
Here's the corresponding sails models:
// User.js
attributes: {
name: 'string'
}
// Project.js
attributes: {
name: 'string',
client: {
model: 'client'
},
userAssignments: {
collection: 'userAssignment',
via: 'project'
}
}
// UserAssignment.js
attributes: {
userPerms: 'integer',
user: {
model:'user'
},
project: {
model:'project'
}
}
// Client.js
attributes: {
name: 'string',
projects: {
collection: 'project',
via: 'client'
}
}
So lets say the User with the ID=1 wants to access a list of Clients he is allowed to see, he calls
GET /clients/
Speaking in SQL:
SELECT client.*
FROM client
INNER JOIN project ON project.client = client.id
INNER JOIN user_assignment ON project.id = user_assignment.project
WHERE user_assignment.user = 1 and user_perms > 4
GROUP BY client.id;
And then also if we have certain Project managers, they can update associated UserAssignments etc.
Basically I thought the permissions could be based on role associations.
I tried several ways to implement this functionality. I tried _permission_read, _permission_write columns for all rows and other stuff like using populates for this but nothing seems to work right.
The above example is just a excerpt of many different kinds of models which I can filter based on SQL couldn't do nicely with Sails/Waterline.
Do I need custom SQL queries for this?
Is it possible to do this neatly with Sails?
Do I misunderstand policies and is there a way to implement such requirements with them?
Or shall I use SQL views instead of tables?
Thanks in advance!

Update user with Admin SDK

I am trying to update some user data via the admin SDK. I thought this would work
function directoryUpdate(userId, userDept, userLocation, userPhone, userTitle) {
var update = {
organizations:
{
name: "Next Step Living",
title: userTitle,
primary: true,
type: "work",
department: userDept,
location: userLocation
},
phones:
{
value: userPhone,
type: "work",
primary: true,
}
};
update = AdminDirectory.Users.update(update, userId);
Logger.log('User %s updated with result %s.', userId, update)
return true;
}
but it is not updating the organization or phone data on the record. It also does not throw any kind of error.
three questions, what is the proper syntax to do this update, I assume this works like the API update and behaves like an upsert, is that true, and what is the best practice for capturing any errors during the update. I would like to return a false when the update fails and capture that info. Thanks in advance for your help.
Thanks for your question!
This "inspired" me to work out how the update API worked, as I had got as far as retrieving a User object, updating the properties but had not worked out how to persist the data back to Google.
So, here's my prototype code, which appears to work (the objective being to reset the user's password based on entries in a spreadsheet).
It doesn't seem the most elegant code to me, being that there are two round-trips to the Admin API, and we have to post the email address twice, but I guess that is a side-effect of the JSON API.
var emailAddress = userListSheet.getRange(row, 1).getValue();
var password = userListSheet.getRange(row, 2).getValue();
Logger.log('Email: %s, Password: %s', emailAddress, password);
// Reset user's password
var user = AdminDirectory.Users.get(emailAddress);
user.password = password;
if (changePasswordAtNextLogin == 'Yes') {
user.changePasswordAtNextLogin = true;
}
AdminDirectory.Users.update(user, emailAddress);
Figured out the syntax issue. You do need a set of [] around the name value pairs under organization and phones. organizations:[{....}], phones:[{...}]}; and no, at the end of primary: true under phones. Also changed it from an update to a patch but not sure if that was really required;
update = AdminDirectory.Users.patch(update, userId);
And Yes, it did behave like an upsert and modified existing data and added new data just like the API.
Still need to figure out the best way to capture any errors though so if you have any suggestions please post them.
Looks like supplying an invalid email address is a fatal error that can not be caught and dealt with in code. What I did was get all the primary emails out of Google, store them in an array, and validate that the email I was using was in that list prior to running the update. Since everything else is just a string or logical replacement it should not throw any errors so I am confident that the script will not fail. Now all I have to worry about is the time limit.