Resource in Users.Undelete in AdminDirectory API (Google-Apps-Script) - google-apps-script

AdminDirectory.Users.undelete(resource, userKey)
UserKey is the UserID/UserKey. Not sure what is the resource here.

Answer:
The only parameter required by Directory API: Users: undelete is orgUnitPath.
More Information:
As per the documentation:
In the request body, supply data with the following structure:
{
"orgUnitPath": string
}
Where the orgUnitPath is the path to the Organizationan unit you wish to restore the user to. You can get a list of your Organizational units from the [Orgunits: list]9v) method of the same API.
The orgUnitPath parameter needs to be preceded with a /, as per the resource representation documentation on Orgunits:
orgUnitPath: The full path to the organizational unit. The orgUnitPath is a derived property. When listed, it is derived from parentOrgunitPath and organizational unit's name. For example, for an organizational unit named 'apps' under parent organization '/engineering', the orgUnitPath is '/engineering/apps'. In order to edit an orgUnitPath, either update the name of the organization or the parentOrgunitPath.
So as for this example, you would need to provide the following resource:
{
"orgUnitPath": "/engineering/apps"
}
Something to remember:
When undeleting a user, unlike the delete method, you can not specify their email address in the userKey field to restore them. This is mentioned in the undelete documentation:
userKey: Identifies the user in the API request. The value must be the user's unique user ID.
Code Example:
function undeleteUser() {
AdminDirectory.Users.undelete(
{
orgUnitPath: '/My-Org-Unit-Path'
},
'21-character-unique-user-id'
);
}
The unique user ID can be obtained from a Users: list request.
References:
Directory API - Users: undelete
Orgunits - Resource Representation
Directory API - Users: list

Related

What does {+} mean in api variable types?

[![enter image description here][1]][1][![enter image description here][2]][2]This variable type was specified in an API. What does it mean? An object with properties?
webinar_id* {+}
It says string but when I input a string for webinar_id I get a 400 missing required parameter.
The linked document shows you that webinar_id is a string that is obtained by the call from section 1. Section 1 also specifies an array called schedules, and since the API call in question asks for an integer called schedule it is logical to assume this is the array of the index previously returned in the section 1 JSON response.
EDIT: webinar_id is also a string and schedule is also an int in the response from the call of section 2. I assume those will be identical to those from section 1.
The fact that {+} indicates re-using values from other requests is outlined in the subscript in section 3.
{+} webinar_id and schedule must be obtained from a previous API call to retrieve the details from whatever specific webinar you want to register the person to.
Hope that helps. It mostly just comes down to careful reading of the documentation document (which you should be glad you have, things aren't always this explicit!)

jMeter not applying variable to header manager

I'm using Apache JMeter 3.2 r1790748 on Mac.
I have a setUp Thread Group making an authentication call. The call works and outputs the tokens correctly. Now I need to pass that token to the HTTP Header Manager for all the calls I'm making.
First of all, here's my token json output:
{
"access_token": "aaaaaa555555555",
"token_type": "Access",
"user_id": "5555"
}
Here's what my HTTP Header manager looks like:
1 value: Authorization : Bearer ${access_token}
My network call:
GET https://my_server.com/some_path
GET data:
[no cookies]
Request Headers:
Connection: close
Authorization: Bearer ${access_token}
Host: my_server.com
User-Agent: Apache-HttpClient/4.5.3 (Java/1.8.0_91)
As you can see, the variable access_token is not being replaced with the value from the setup call.
What I've tried:
BeanShell PostProcessor:
I created this script, and it actually parses and outputs the access_token properly:
import org.apache.jmeter.protocol.http.control.Header;
import net.minidev.json.JSONObject;
import net.minidev.json.parser.JSONParser;
String jsonString = prev.getResponseDataAsString();
log.info("jsonString = " + jsonString);
JSONParser parser = new JSONParser(JSONParser.MODE_JSON_SIMPLE);
JSONObject json = (JSONObject) parser.parse(jsonString);
String access_token = json.getAsString("access_token");
log.info("access_token = " + access_token);
vars.put("access_token", access_token);
JSON Extractor:
Apply to: Main sample and sub-samples
Variable names: access_token
JSON Path expressions: access_token
Match No. (0 for Random): 1
Compute concatenation var (suffix _ALL): unchecked
Default Values: none
Any ideas as to why the header manager is not applying the value of the access_token result?
Thanks!
Since you set a variable in setUp Thread Group, you cannot use it in another thread groups, since thread groups don't share variables, only properties.
So in order to pass authentication, you need to save it as a property:
${__setProperty(access_token, ${access_token})};
In this example I am using value of variable named access_token (already set, but only available in setUp thread group) to set property with the same name, which will be available across thread groups. Or change BeanShell post-processor, add:
props.put("access_token", access_token);
And then in the other thread group, you retrieve it using __P or __property function:
${__P(access_token)}
Also keep in mind that HTTP Header Manager initializes before any thread starts, so you can't use variables there for that reason too. Check this question for instance.
If you still see empty value, I recommend adding Debug Sampler (with both JMeter Properties and JMeter Variables enabled) in both thread groups, and checking where the breakage is (on saving or retrieving).
As per Functions and Variables chapter of the JMeter User Manual
Variables are local to a thread; properties are common to all threads, and need to be referenced using the __P or __property function
So the variable you define in the setUp Thread Group cannot be accessed by:
other threads in the same Thread Group
other threads outside the Thread Group
So my recommendations are:
Switch to JMeter Properties instead of Jmeter Variables, JMeter Properties are global to all threads and in fact the whole JVM instance
Switch to JSR223 PostProcessor with Groovy language instead of Beanshell PostProcessor, JSR223 Elements performance is much better, moreover Groovy has built-in JSON support.
So:
The relevant Groovy code for getting access_token attribute value and storing it into the relevant property would be :
props.put('access_token', new groovy.json.JsonSlurper().parse(prev.getResponseData()).access_token)
You can refer the value in the HTTP Header Manager (or wherever you require) as:
${__P(access_token,)}

How do I ensure Firebase database structure using anonymous auth?

I have a public-input type app using Firebase, with anonymous auth. The user data is used to create points on a map. Each anonymous user can only edit the data inside the node matching their auth id - via security rules.
However, my app depends on a certain database structure. How do I ensure my database structure/integrity using anonymous auth, since the database url is client-side readable?
I think it is possible with security and validation rules, but I'm not sure. Maybe deny children creation in a node? This would be necessary to ensure the schema is followed.
Each auth node can have many key nodes, but I would want to limit this Firebase-side. And each key node must follow the schema below (so I can pull out the geojson easily). Below is my current setup - wondering what is missing?
"features" : {
"5AGxfaK2q8hjJsmsO3PUxUs09Sz1" : {
"-KS3R4sWPdcDkrxyIFX6" : {
"geometry" : {
"coordinates" : [ -81.88247680664062, 38.884619201291905 ],
"type" : "Point"
},
"properties" : {
"color" : "#2be",
"title" : ""
},
"type" : "Feature"
},
Authentication and database schema are completely separate topics. You ensure database schema by using a combination of .write and .validate rules in your security doc, not by anything to do with your authentication provider (i.e. Anonymous authentication).
This is described in detail in our database security guide.
A quick summary:
hasChildren: specify required fields
newData: refer to the data being written
data: refer to data already in the database
.validate: specify data schema using things like newData.isString() or newData.val() == data.val() + 1
Keep in mind that .validate rules are only run for non-null values. Thus, if you want to try something like !data.exists() (i.e. you can only write to this path once and can't modify it later) or newData.exists() (i.e. you can't delete this data) then you need to specify those in a .write rule.
Refer to the guide for more detail.

Google Drive Windows App to/from fileId - items with same names, and multiple parents

I'm trying to translate from a Google Drive link on the web (well, the fileId anyway) to the Windows Google Drive app's path on the hard disk, and back again.
It would be helpful if there was something in the API for this (eg produce a path excluding the C:\Users\[User]\Google Drive\ from a file/folder ID, and vice versa), but there isn't.
So far I do:
Windows Path to ID: get the first folder of the path and (starting from the root) look for a matching folder, then repeat until finished (possibly with a file name). PROBLEM: Items can be called the same thing, whether files or folders or combinations of both, which is tricky in Windows. The app adds a number ' (1)' and so on, which I have to catch, but how can I know which item ID is the correct one? I believe that numbering is based on date but I'm not sure. So I can potentially end up with multiple results and no way to tell which is which.
ID to Windows Path: take the name of the file/folder from the ID, then keep adding the parent folder(s) until I build up a path. PROBLEM: same as 1 above, if there are multiple matching items then I can't tell which I should use when translating to Windows. PROBLEM: Apparently items in Google Drive can have more than one parent. Not sure how that works in the Windows app.
Can anyone help me fine tune how I do this, or tell me the exact details of how the Google Drive app does it? Code is welcome but not required, and I in turn can provide the code I use if needed.
I'm not sure if I fully understand the question, but I try to smack an answer anyway:
1/ assuming you have a Windows path,
C:\Users\User\Google Drive\myfile.ext
you create a file with a similar path on GooDrive iterating your path's tokens
recursively creating a tree structure on GooDrive. If the tree nodes (folders/files) exist, return ID's, otherwise create the objects. The main difference in GooDrive is that title query may return multiple objects (list of folders/files). Bad luck, you either use the first one or quit with an error.
global path = "C:\Users\User\Google Drive\myfile.ext"
createTree(String path) {
rootFolderId = create your root or use GooDrive root
fileId = iterate (firstToken(path, "\"), rootFolderId);
}
iterate(title, parentFolderId) {
ID (or multiple IDs) = search for title in parentFolderId
if (multiple IDs exist)
BOOM - report error and quit or use the first one
if (token not last) {
if (single ID for title exists) {
folderId = found ID
} else {
folderId = createFolder with title and parentFolderId metadata
}
iterate(nextToken(path, "\"), folderId)
} else { (last token represent file)
if (single ID for title exists) {
fileId = found ID
} else {
fileId = createFile with title and parentFolderId metadata
}
return fileId
}
}
You did not specify the language, but in case it is Java, you can see similar procedure here in the createTree() method (it is Android code, so there is a lot of Android specific goo there, sorry)
2/ assuming you have a Google Drive fileId, you construct the Windows path with this pseudocode (going from bottom up to the root). Again, you may have multiple parents you have to deal with (error or multiple paths with links to a single object)
String path = fileId's title
while () {
parentID = get fileId's parent
if (multiple parentIDs exist)
BOOM - report error and quit or construct multiple paths
(multiple paths would represent file/folder links)
if (parentID not valid or parentId's title not valid)
break
path = parentID's title + "\" + path
if (parentID's title is your root)
break
}
One more thing: You say "Folders and files can be called the same thing..."
In GooDrive, look at the MIME type, there is a specific MIME type "application/vnd.google-apps.folder" that tells you it is a folder. Also, any parentId metadata represents folder, since files can't be parents.
Good Luck

REST: Updating multiple records

I need to update multiple records using a single HTTP request. An example is selecting a list of emails and marking them as 'Unread'. What is the best (Restful) way to achieve this?
The way I doing right now is, by using a sub resource action
PUT http://example.com/api/emails/mark-as-unread
(in the body)
{ids:[1,2,3....]}
I read this site - http://restful-api-design.readthedocs.io/en/latest/methods.html#actions - and it suggests to use an "actions" sub-collection. e.g.
POST http://example.com/api/emails/actions
(in the body)
{"type":"mark-as-unread", "ids":[1,2,3....]}
Quotes from the referenced webpage:
Sometimes, it is required to expose an operation in the API that inherently is non RESTful. One example of such an operation is where you want to introduce a state change for a resource, but there are multiple ways in which the same final state can be achieved, ... A great example of this is the difference between a “power off” and a “shutdown” of a virtual machine.
As a solution to such non-RESTful operations, an “actions” sub-collection can be used on a resource. Actions are basically RPC-like messages to a resource to perform a certain operation. The “actions” sub-collection can be seen as a command queue to which new action can be POSTed, that are then executed by the API. ...
It should be noted that actions should only be used as an exception, when there’s a good reason that an operation cannot be mapped to one of the standard RESTful methods. ...
Create an algorithm-endpoint, like
http://example.com/api/emails/mark-unread
bulk-update is an algorithm name, a noun. It gets to be the endpoint name in REST, the list of ids are arguments to this algorithm. Typically people send them as URL query arguments in the POST call like
http://example.com/api/emails/mark-unread?ids=1,2,3,4
This is very safe, as POST is non-idempotent and you need not care about any side effects. You might decide differently and if your bulk update carries entire state of such objects opt for PUT
http://example.com/api/emails/bulk-change-state
then you would have to put the actual state into the body of the http call.
I'd prefer a bunch of simple algo like mark-unread?ids=1,2,3,4 rather than one monolithic PUT as it helps with debugging, transparent in logs etc
It a bit complicated to get array of models into an action method as argument. The easiest approach is to form a json string from your client and POST all that to the server (to your action mehtod). You can adopt the following approach
Say your email model is like this:
public class Email
{
public int EmailID {get; set;}
public int StatusID {get; set;}
// more properties
}
So your action method will take the form:
public bool UpdateAll(string EmailsJson)
{
Email[] emails = JsonConvert.DeserializeObject<Emails[]>(EmailsJson);
foreach(Email eml in emails)
{
//do update logic
}
}
Using Json.NET to help with the serialization.
On the client you can write the ajax call as follows:
$.ajax({
url: 'api/emailsvc/updateall',
method: 'post',
data: {
EmailsJson: JSON.stringify([{
ID: 1,
StatusID:2,
//...more json object properties.
},
// more json objects
])
},
success:function(result){
if(result)
alert('updated successfully');
});