I have one Odata service , which is providing me the data and I am able to display this data on table. We are going to deploy this application to Launchpad. Now we have this requirement in which logged in user must get the data according to his/her login ID. So If my user ID is XXXXX , I should get the records only for XXXXX. I am unable to understand the process flow. Shall we implement the logic in Odata itself or should I get all the data and filter the model on UI, before displaying it.
Regards,
MS
In oData itself you can access login user by sy-uname. using that user you can filter your data.
OR
In front end you can access login user by below code
var vUrl = "proxy/sap/bc/ui2/start_up";
var oxmlHttp = null;
oxmlHttp = new XMLHttpRequest();
oxmlHttp.onreadystatechange = function() {
if (oxmlHttp.readyState == 4 && oxmlHttp.status == 200) {
var oUserData = JSON.parse(oxmlHttp.responseText);
vUser = oUserData.id;
}
};
oxmlHttp.open( "GET", vUrl, false );
oxmlHttp.send(null);
You have to handle this in Odata only. Get User id from UI using
var storename = sap.ushell.Container.getService("UserInfo").getId();
and set it to Odata to filter and send back the results.
You should handle such requirements in the Service level (OData level), not in the UI.
In DPC_EXT class variable SY-UNAME gives you the logged in user. So you should filter your records by deriving more information from that.
Related
I am trying to use Microsoft Graph API to update another user in Active Directory.
I have the following permissions set for both user and application at https://apps.dev.microsoft.com/
I've requested the following scopes:
Directory.ReadWrite.All
User.ReadWrite.All
Group.ReadWrite.All
I am able to get a listing of all users in the directory, but when trying to update (in this case, the city) it fails:
GraphServiceClient graphClient = SDKHelper.GetAuthenticatedClient ();
var usersResponse = graphClient.Users.Request ().GetAsync ();
var users = usersResponse.Result;
// hard coding user id for now
var userId = "9a5b83cd-85ff-4ad1-ab2f-b443941a518e";
var user = users.FirstOrDefault (m => m.Id == userId);
if (user != null) {
user.City = "New York";
await graphClient.Me.Request ().UpdateAsync (user);
}
I get:
{
Code : Authorization_RequestDenied
Message : Insufficient privileges to complete the operation.
Inner error
}
The user I am logged in as is a Global Administrator of the directory.
I took the JWT token, headed over to https://jwt.io and these are the roles I am seeing:
Directory.Read.All
Directory.ReadWrite.All
Files.ReadWrite
Group.ReadWrite.All
Mail.Send
User.Read
User.Read.All
User.ReadWrite.All
Do I need other permissions to make this happen?
At the end of the day, I'd like to create a console app (not web app) that I can update other user information in the directory. But I figured using this sample app provided by Microsoft is a good start.
The reason you're seeing this is because you're passing the complete user object rather than only the city property. In other words, you're attempting to update every property in that user record, including several that are read-only.
This is one of those cases where having an SDK that wraps a REST API can be result in some confusing errors. As REST API, it is stateless so passing in the entire user property set is telling the API you want to PATCH all of those values.
You're also passing in a different user object into the me object (i.e. you're replacing all of your property values with this other user's property values):
await graphClient.Me.Request().UpdateAsync(user);
Instead, try this:
GraphServiceClient graphClient = SDKHelper.GetAuthenticatedClient ();
// hard coding user id for now
var userId = "9a5b83cd-85ff-4ad1-ab2f-b443941a518e";
await graphClient.Users[userId].Request ().UpdateAsync(new User
{
City = "New York"
});
I have a query that runs and can see the results. But while trying to save the query as a view table, I get error message saying
Failed to save view. No suitable credentials found to access Google
Drive. Contact the table owner for assistance.
I think the problem is caused by a table used in the query. The table is uploaded from a google sheet (with source URI), own by me. I have tried to enable Google Drive API from the project but no luck. Not sure how I can give BigQuery access to Google Drive.
I suspect the problem you are hitting is one of OAuth Scopes. In order to talk to the Google Drive API to read data, you need to use credentials that were granted access to that API.
If you are using the BigQuery web UI and have not explicitly granted access to Drive, it won't work. For example, the first time I tried to "Save to Google Sheets", the BigQuery UI popped up an OAuth prompt asking me to grant access to my Google Drive. After this it could save the results. Try doing this to make sure your credentials have the Drive scope and then "Save View" again.
If you are using your own code to do this, you should request scope 'https://www.googleapis.com/auth/drive' in addition to the 'https://www.googleapis.com/auth/bigquery' scope you are already using to talk to BigQuery.
If you are using the bq client, it has been updated to request this scope, but you may need to re-initialize your authentication credentials. You can do this with bq init --delete_credentials to remove the credentials, then your next action we re-request credentials.
Using Google App Script this worked for me:
function saveQueryToTable() {
var projectId = '...yourprojectid goes here...';
var datasetId = '...yourdatesetid goes here...';
var sourceTable = '...your table or view goes here...';
var destTable = '...destination table goes here...';
var myQuery;
//just a random call to activate the Drive API scope
var test = Drive.Properties.list('...drive file id goes here...')
//list all tables for the particular dataset
var tableList = BigQuery.Tables.list(projectId, datasetId).getTables();
//if the table exist, delete it
for (var i = 0; i < tableList.length; i++) {
if (tableList[i].tableReference.tableId == destTable) {
BigQuery.Tables.remove(projectId, datasetId, destTable);
Logger.log("DELETED: " + destTable);
}
};
myQuery = 'SELECT * FROM [PROJECTID:DATASETID.TABLEID];'
.replace('PROJECTID',projectId)
.replace('DATASETID',datasetId)
.replace('TABLEID',sourceTable)
var job = {
configuration: {
query: {
query: myQuery,
destinationTable: {
projectId: projectId,
datasetId: datasetId,
tableId: destTable
}
}
}
};
var queryResults = BigQuery.Jobs.insert(job, projectId);
Logger.log(queryResults.status);
}
The 'trick' was a random call to the Drive API to ensure both the BigQuery and Drive scopes are included.
Google Apps Script Project Properties
recently I've spent some time digging into AspNet.Security.OpenIdConnect.Server. I use MVC sample as a code base for my client/server apps.
The thing I need to implement now is obtaining a user's profile info from an external provider (Google) and saving the info into the server's database.
What is the right place for getting and saving a profile's info and a proper way to implement it?
Note: since ASOS (AspNet.Security.OpenIdConnect.Server) only handles the OAuth2/OpenID Connect server part, it's actually not involved in the authentication part, and thus doesn't directly deal with the external providers you configure.
To achieve what you want, the best approach is to configure the Google middleware to extract more information from the user object returned in the user profile response and to persist them in the authentication cookie so you can later retrieve them in your application code.
app.UseGoogleAuthentication(options => {
options.ClientId = "client_id";
options.ClientSecret = "client_secret";
options.Events = new OAuthEvents {
OnCreatingTicket = context => {
// Extract the "language" property from the JSON payload returned by
// the user profile endpoint and add a new "urn:language" claim.
var language = context.User.Value<string>("language");
context.Identity.AddClaim(new Claim("urn:language", language));
return Task.FromResult(0);
}
};
});
If the response doesn't include the data you need, nothing prevents you from using context.Backchannel to make another HTTP call to retrieve more data from a different Google endpoint.
I'm experimenting with Google Apps Script and Twitter, and I'd like to be able to access multiple Twitter accounts through one spreadsheet. At the moment I've attempted the approach below (a unique OAuthService name for each Twitter account), and this kind-of works but it clunky because I have to randomly authorize one account (and not more than one) each time the script is run, and the popup dialog doesn't tell me which account (i.e. id) I'm authenticating for.
Ideally, I'd like to force each user to give Twitter permission on first use, then store that token for later use - is this possible withe Google App Script?
Thanks.
function oAuth(id) {
var oauthConfig = UrlFetchApp.addOAuthService(NS_TWITTER + id);
oauthConfig.setAccessTokenUrl("https://api.twitter.com/oauth/access_token");
oauthConfig.setRequestTokenUrl("https://api.twitter.com/oauth/request_token");
oauthConfig.setAuthorizationUrl("https://api.twitter.com/oauth/authorize");
oauthConfig.setConsumerKey(CONSUMER_KEY);
oauthConfig.setConsumerSecret(CONSUMER_SECRET);
};
and then
var options =
{
"method": "GET",
"oAuthServiceName":NS_TWITTER + id,
"oAuthUseToken":"always",
};
try {
var result = UrlFetchApp.fetch(feed, options);
}
Yes, is possible.
To store the token values use userProperties (Docs here) or CacheService wich remains for 20 minutes in cache (Docs here).
Example storing token using UserProperties
UserProperties.setProperty('token', 'value');
var token = UserProperties.getProperty('token');
Example storing token using CachService
// Gets a cache that is private to the current user
var cache = CacheService.getPrivateCache();
cache.put('token', 'value');
var token = cache.get('token');
After building you cache solution you need to check if the token is valid with twitter API. If it's invalid you should require the auth again.
I tried to use the google apps reseller api with google apps script. To use oauth I need the AuthServiceName. what is the right name? "apps" does not work.
AuthServiceName is defined in your application, its not dependent on the API that you are connecting to, i would suspect that you may not have completed all the steps necessary or that your oauth call is not properly structured.
Here is an example of a call that retrieves the details of domains.
function getCustomer() {
//set up oauth for Google Reseller API
var oAuthConfig1 = UrlFetchApp.addOAuthService("doesNotMatter");
oAuthConfig1.setRequestTokenUrl("https://www.google.com/accounts/OAuthGetRequestToken?scope=https://www.googleapis.com/auth/apps.order.readonly");
oAuthConfig1.setAccessTokenUrl("https://www.google.com/accounts/OAuthGetAccessToken");
oAuthConfig1.setAuthorizationUrl("https://www.google.com/accounts/OAuthAuthorizeToken?oauth_callback=https://script.google.com/a/macros");
oAuthConfig1.setConsumerKey(CONSUMER_KEY);
oAuthConfig1.setConsumerSecret(CONSUMER_SECRET);
var options1 = {oAuthServiceName:"doesNotMatter", oAuthUseToken:"always",
method:"GET", headers:{"GData-Version":"3.0"}, contentType:"application/x-www-form-urlencoded"};
//set up user profiles url
var theUrl = "https://www.googleapis.com/apps/reseller/v1/customers/somedomain.com";
//urlFetch for customer list
var customerInfo = "";
try {
var response = UrlFetchApp.fetch(theUrl,options1);
customerInfo = response.getContentText();
} catch(problem) {
Logger.log(problem.message);
}
Logger.log(customerInfo);
}
This will work if
You have a reseller account (I guess i.e. I did not test on my non reseller account)
You have create a project in the API console, and enabled the Reseller API
You know your SECRET and KEY lifted form the console
I have use a read.only scope which is safe, if not you need to set up your tests in the sand box
Let me know if you need any more clarifications