Xpages SSJS Create Administration Process - xpages

Has anyone been able to get SSJS CreateAdministrationProcess to work? I have searched for functioning code but was not able to find any.
I am trying to create an adminP request in SSJS to set a users password. I can't use the ?changepassword in the url method because we do not allow web users access to the NAB.
I am using OAUTH and when I try to hash and update the password directly to the NAB it without an adminp request, it creates problems with the current client session, logging them out and then locking them out.
I assume this is because I changed the credential tokens on the server but not on the client and when it realizes this it thinks I'm trying to authenticate over and over and locks me out.
If I can't get the SSJS to work I am going to write it in a lotusscript agent and call the agent from SSJS, but for posterity sake I wanted to get AdminP requests to work from SSJS directly.
Here is my code:
var hashednew = session.hashPassword(thenewpw)
nabDoc.replaceItemValue("HTTPPassword",hashednew)
var dt:NotesDateTime = session.createDateTime("Today 12");
nabDoc.replaceItemValue("HTTPPasswordChangeDate",dt)
dt.recycle()
var nabServerAccessView:NotesView = nabDB.getView("($ServerAccess)")
nabDB.DelayUpdates = false;
var AdminP=sessionAsSigner.CreateAdministrationProcess("abcServerName/Co")
var AdminPNoteId=AdminP.SetUserPasswordSettings(#Name("[ABBREVIATE]" ,#UserName()), 0, 0, 0, True)
nabDoc.save(true,true)
nabServerAccessView.refresh()
It is crashing at the line:
var AdminP=sessionAsSigner.CreateAdministrationProcess("abcServerName/Co")
and the server error is:
Error calling method 'CreateAdministrationProcess(string)' on an object of type 'lotus.domino.local.Session [Static Java Interface Wrapper, lotus.domino.local.Session: lotus.d
AS A FOLLOWUP,
The original code I posted had more than the uppercase/lowercase issue, in practice. I was able to get it to work, but the way I was updating to the NAB directly was wrong. I found a better way to do the password change using SSJS with the following snippet, and it's pretty simple. Of course you have to validate the old password and complexity of the new password first, but once you've done that you can run the following:
try {
var AdminP=sessionAsSignerWithFullAccess.createAdministrationProcess(server)
var chgPW=AdminP.changeHTTPPassword(theuser,theoldpw,thenewpw)
} catch(e) {print("AdminProcess configure error: " + e)}

In my opinion the problem is in naming convention - Java methods start with lower case letters.
var AdminP=sessionAsSigner.createAdministrationProcess("abcServerName/Co")
var AdminPNoteId=AdminP.setUserPasswordSettings(#Name("[ABBREVIATE]" ,#UserName()), 0, 0, 0, True)

Please check your ACL settings: Is "Maximum internet name and password" set to "Manager" or "Designer"?

Related

How to pass password only to HTTP request?

I am using JavaScript in the scripting engine in a program called Directory Opus. It seems to use a flavor of JavaScript more like MS JScript. I mention that because to say not all things JavaScript (ES6) will work with what it accepts. My question is this: in a HTTP request like the code I show should I be able to pass user credentials to the open command if only a password is required? This request is for VLC player and their instructions are to leave the username blank. If put the same URL in a browser it will prompt with a password once, I will put in the password “vlcremote”, leave the username blank and it will return the status. When I use with the syntax, I show, it returns an error when the open command uses “” as a username. If I put a random user name the request returns a limited result but denies access to the data it should give. Is there a better way to do this?
function getValues(webUrl)
{
var xhr = new ;
var url = webUrl;
xhr.open("GET", url, false, "", "vlcremote");
xhr.setRequestHeader("Content-type", "text/xml");
xhr.setRequestHeader("Authorization", "Basic")
xhr.send()
DOpus.Output(xhr.readyState)
var xmlText = xhr.responseText;
DOpus.Output(xmlText)
}
getValues("http://127.0.0.1:8080/requests/status.xml");

Discord <#!userid> vs <#userid>

so I'm creating a bot using Node.JS / Discord.JS and I have a question.
On some servers, when you mention a user, it returns in the console as <#!userid> and on other it returns as <#userid>.
My bot has a simple points / level system, and it saves in a JSON file as <#!userid>, so on some servers when trying to look at a users points by mentioning them will work, and on others it won't.
Does anyone have any idea how to fix this? I've tried to find an answer many times, and I don't want to have it save twice, once as <#!userid> and then <#userid>. If this is the only way to fix it then I understand.
Thanks for your help!
The exclamation mark in the <#!userID> means they have a nickname set in that server. Using it without the exclamation mark is more reliable as it works anywhere. Furthermore, you should save users with their id, not the whole mention (the "<#userid>"). Parse out the extra symbols using regex.
var user = "<#!123456789>" //Just assuming that's their user id.
var userID = user.replace(/[<#!>]/g, '');
Which would give us 123456789. Their user id. Of course, you can easily obtain the user object (you most likely would to get their username) in two ways, if they're in the server where you're using the command, you can just
var member = message.guild.member(userID);
OR if they're not in the server and you still want to access their user object, then;
client.fetchUser(userID)
.then(user => {
//Do some stuff with the user object.
}, rejection => {
//Handle the error in case one happens (that is, it could not find the user.)
});
You can ALSO simply access the member object directly from the tag (if they tagged them in the message).
var member = message.mentions.members.first();
And just like that, without any regex, you can get the full member object and save their id.
var memberID = member.id;

Setting the ACL when creating a new database via JS in XPages

I am creating a new database using JS from an action button. The following sequence happens:
When the database is created the -default- access is set to Manager which it has to be.
I then create several aclEntries. The first entry created for the current user and set them as a type person and having Manager rights
I then create several other entries with varying right and save the ACL.
If I open the Db the ACL looks and acts correctly except the -default- has an access level of Manager.
So I tried change my code to set the access level for -default- to Author in various ways, all resulting in an exception:
Change -default- to Author and save
First save the ACL as above, then change the -default- entry and save
create the ACL object newly using var newACL = db.getACL(), change and try to save
It seems that it does not recognize me as a manger in the ACL.
Q: How do I change the -default- access away from manager?
Probably the easiest way to get a good default ACL is using a template database. All entries in your template that come in square brackets are copied into the new database as ACL entries.
So in your template you would have
[-Default-]=Author and [Anonymous]=No Access which results in
-Default-=Author and Anonymous=No Access in the new DB
Update
Easier that it looks. You need to make sure to get the entries right...
Use this function:
function makeDB(dbName) {
var server = database.getServer();
var you = #UserName();
var dbDir = session.getDbDirectory(server);
var db = dbDir.createDatabase(dbName);
var acl = db.getACL();
acl.createACLEntry(you,6);
if (server != "" && server != you) {
acl.createACLEntry(server,6);
}
var def = acl.getEntry("-Default-");
def.setLevel(3);
acl.save();
}
Then you call the function using:
makeDB("someFancyDBName");
In the function we make sure that you, who runs the script and the server where it runs are both in the ACL as managers (including the case of a local database, where in the Notes client the server is empty and in the web preview would be your user name).
Works like a charm. If it doesn't work for you, there are a few things to check:
Does it work on local (no server involved)?
Do you have errors on the console?
What access level do you have in the server ECL
Check the "max Internet access" of the database
The previous answer (obsolete):
Other than that it is a little trickier...
You create the new database:
var db:Database = [... whatever you have todo here ...];
var acl:Acl = db.getAcl();
// Do whatever you do, don't touch -Default-
acl.save();
acl.recycle();
var dbURL = db.getUrl(); // <-- off my head might be slightly different name
db.recycle();
// Now the real work
var db2 = session.evaluate(dbUrl);
var acl2 = db2.getAcl();
// Change default here;
Typed off my head, contains typos.
This should work. Let us know how it goes

My program turns a spreadsheet into an Excel-file. But it only works for one user

I've made a larger (1000+ lines of code) App Script. It works great, for me. No other user can run it. I want them to be able to run it as well, and I can not figure out why they can't.
The problem occurs on this part:
var id = 'A_correct_ID_of_a_Google_Spreadsheet';
var SSurl = 'https://docs.google.com/feeds/';
var doc = UrlFetchApp.fetch(SSurl+'download/spreadsheets/Export?key='+id+'&exportFormat=xls',googleOAuth_('docs',SSurl)).getBlob();
var spreadsheet = DocsList.createFile(doc);
The function (and structure) was published here: other thread
function googleOAuth_(name,scope) {
var oAuthConfig = UrlFetchApp.addOAuthService(name);
oAuthConfig.setRequestTokenUrl("https://www.google.com/accounts/OAuthGetRequestToken?scope="+scope);
oAuthConfig.setAuthorizationUrl("https://www.google.com/accounts/OAuthAuthorizeToken");
oAuthConfig.setAccessTokenUrl("https://www.google.com/accounts/OAuthGetAccessToken");
oAuthConfig.setConsumerKey('anonymous');
oAuthConfig.setConsumerSecret('anonymous');
return {oAuthServiceName:name, oAuthUseToken:"always"};
}
I can't see any reason why the program only would run for one user. All the files are shared between all the users and ownership have been swapped around.
When a script uses oAuth (googleOAuth_(name,scope) in you case) it needs to be authorized from the script editor, independently from the other authorization that the user grands with the "normal" usual procedure.
This has been the object of an enhancement request for quite a long time and has no valid workaround as far as I know.
So, depending on how your script is deployed (in a SS or a Doc or as webApp) you might find a solution or not... if, as suggested in the first comment on your post, you run this from a webapp you can deploy it to run as yourself and allow anonymous access and it will work easily, but in every other case your other users will have to open the script editor and run a function that triggers the oAuth authorization process.

Monotouch/iPhone - Call to HttpWebRequest.GetRequestStream() connects to server when HTTP Method is DELETE

My Scenario:
I am using Monotouch for iOS to create an iPhone app. I am calling ASP.NEt MVC 4 Web API based http services to login/log off. For Login, i use the POST webmethod and all's well. For Logoff, i am calling the Delete web method. I want to pass JSON data (serialized complex data) to the Delete call. If i pass simple data like a single string parameter as part of the URL itself, then all's well i.e. Delete does work! In order to pass the complex Json Data, here's my call (i have adjusted code to make it simple by showing just one parameter - UserName being sent via JSON):
HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create("http://localhost/module/api/session/");
req.ContentType = "application/json";
req.CookieContainer = jar;
req.Method = "Delete";
using (var streamWrite = new StreamWriter(req.GetRequestStream()))
{
string jSON = "{\"UserName\":\"" + "someone" + "\"}";
streamWrite.Write(jSON);
streamWrite.Close();
}
HttpWebResponse res = (HttpWebResponse)req.GetResponse();
on the server, the Delete method looks has this definition:
public void Delete(Credentials user)
where Credentials is a complex type.
Now, here's the issue!
The above code, gets into the Delete method on the server as soon as it hits:
req.GetRequestStream()
And hence the parameter sent to the Delete method ends up being null
And here's the weird part:
If i use the exact same code using a test VS 2010 windows application, even the above code works...i.e it does not call Delete until req.GetResponse() is called! And in this scenario, the parameter to the Delete method is a valid object!
QUESTION
Any ideas or Is this a bug with Monotouch, if so, any workaround?
NOTE:
if i change the Delete definition to public void Delete(string userName)
and instead of json, if i pass the parameter as part of the url itself, all's well. But like i said this is just a simplified example to illustrate my issue. Any help is appreciated!!!
This seems to be ill-defined. See this question for more details: Is an entity body allowed for an HTTP DELETE request?
In general MonoTouch (based on Mono) will try to be feature/bug compatible with the Microsoft .NET framework to ease code portability between platforms.
IOW if MS.NET ignores the body of a DELETE method then so will MonoTouch. If the behaviour differs then a bug report should be filled at http://bugzilla.xamarin.com

Resources