Basic authentication for Swagger-UI not working correctly - owin

I have setup Swagger within my ASP.NET project using NSwag which works fine but I am attempting to add support for authentication.
My authentication model is a simple username/password that uses OAuth using ApplicationOAuthProvider
The URL I use to login is as below
/token
With the POST parameters:
grant_type=password&username=${username}&password=${password}
Now my swagger setup [in Global.asax] is
app.UseSwaggerUi(typeof(Global).Assembly, new SwaggerUiSettings
{
MiddlewareBasePath = "/swagger",
OAuth2Client = new OAuth2ClientSettings
{
ClientId = "my_auth_id",
//ClientSecret = "bar",
AppName = "my",
//Realm = "my_realm",
//AdditionalQueryStringParameters = { { "foo", "bar" } }
},
DocumentProcessors = {
new SecurityDefinitionAppender("oauth2", new SwaggerSecurityScheme
{
Type = SwaggerSecuritySchemeType.Basic,
Description = "Description is set htere",
Flow = SwaggerOAuth2Flow.Password,
AuthorizationUrl = "https://localhost:28866/token?",
TokenUrl = "https://localhost:28866/token",
In = SwaggerSecurityApiKeyLocation.Query
//Scopes = new Dictionary<string,string>
//{
// //{ "read", "Read access to protected resources" },
// { "write", "Write access to protected resources" }
//}
})
},
OperationProcessors =
{
new OperationSecurityScopeProcessor("oauth2")
}
});
I know its a bit messy but I was literally trying every option I could to make it work.
So this actually gives me the Authorize button and a Username and Password field. But when I click login it refreshes the swagger.json but doesnt actually attempt to log in anywhere?

Related

SharePoint Onlinie - Create Drive using graph service client

I am working on one project where I've to create a drive (document library) on SharePoint in not exists.
Using following code:
var newRRRDrive = new Drive
{
Name = "RRRR-Prod1",
Description = "Holds RRRR files",
AdditionalData = new Dictionary<string, object>()
{
{"#microsoft.graph.conflictBehavior","rename"}
}
};
var newDrive = await graphClient
.Sites[site.Id]
.Drives
.Request()
.AddAsync(newRRRDrive);
But this is throwing exception that the request is invalid. I don't know what I doing wrong here.. Any suggestions?
Code: invalidRequest
Message: Invalid request
Inner error:
AdditionalData:
date: 2021-05-30T20:57:40
request-id: ec6ddddddddddddddd0f72d91c8e
client-request-id: ec6ddddddddddddddddddddddddddddddddd
ClientRequestId: ec6dedddddddddddddddddddddddddddddddddddddddddddd
Adding image after implementing soln by Michael
enter image description here
To create a new document library, you can perform the same call as mentioned in the create list instead of using the genericList template value. Use the documentLibrary value.
POST /sites/{site-id}/lists
Content-Type: application/json
{
"displayName": "YourLibraryName",
"list": {
"template": "documentLibrary"
}
}
C# code
var list = new List
{
DisplayName = "Books",
ListInfo = new ListInfo
{
Template = "documentLibrary"
}
};
await graphClient.Sites["{site-id}"].Lists
.Request()
.AddAsync(list);

microsoft bots to teams using nodejs fails with missing activityid when updating the same activity

My code has a simple card carousel which has action button like below:
actions = [
{
"type": "Action.Submit",
"title": "Qualify",
"data": { "action" : "qualify_lead" }
},
{
"type": "Action.OpenUrl",
"title": "Retire",
"url": "{viewUrl}"
},
{
"type": "Action.ShowCard",
"title": "Add Note",
"card": this.noteCard(item.LeadId, "leads")
}
]
I am having a method to handle qualify_lead action like below
async qualifyLead(context:any){
console.log("in qualifyLead:" + JSON.stringify(context.activity))
await context.updateActivity(this.successCard('Lead is qualified'))
}
All I am doing on purpose is to replace entire carousel with a simple text message. But it fails with error:
Error: BotFrameworkAdapter.updateActivity(): missing activity.id
Where do i get this ?
I am using google firebase for this and the wrapper code is like below
const {
TurnContext,
TeamsActivityHandler,
CardFactory,
AttachmentLayoutTypes,
ActionTypes
} = require('botbuilder');
class TeamsConversationBot extends TeamsActivityHandler {
constructor() {
super();
this.leadState =
this.conversationState.createProperty('leadCarouselState');
this.onMessage(async (context:any, next:any) => {
TurnContext.removeRecipientMention(context.activity);
let msg = context.activity.text
const action = context.activity.value
let objNum = ''
let keyword = ''
if(msg === undefined && action === undefined)
msg = 'help'
else if(msg !== undefined){
msg = msg.trim().toLowerCase()
if(msg.indexOf("help") > -1)
msg = 'help'
else{
if(msg.startsWith('lead')){
msg = 'lead'
}
}
}
switch (msg) {
case 'lead':
await this.lead(context, userKey, platform)
break;
case 'qualify_lead':
await this.qualifyLead(context)
break;
}
await next();
});
}
I'm not sure exactly what this.successCard('Lead is qualified') does, but presumably it returns an Activity. To my knowledge, in order for this Activity to replace another one, you need to set it's Id property to match the previous message. That means that, when you send the previous message (i.e. the card), you need to capture the reference that's returned from the send method on the context (e.g. into bot state), and then use it for this new activity.
As I explained in my answer to your other question, you need to save the activity ID in bot state and then apply it to the update that you're sending. The Bot Framework can't update an activity unless you tell it which activity to update, and you do that using an activity ID.
This was the part that saves the ID:
const dict = await this.carouselState.get(turnContext, {});
dict[batchId] = {
[KEYACTIVITYID]: response.id,
[KEYLEADS]: leads
};
And this was the part that applies it to the updated activity:
const update = this.createCarousel(batchId, leads);
update.id = info[KEYACTIVITYID];

Create Folder and Share with Guest User without Microsoft Account in Sharepoint with CSOM

I am quite new in CSOM/Sharepoint development and have an interesting task to solve. Unfortunately I don't make as much progress with some details as I would like.
A customer of mine wants a secure way to exchange confidential documents. Therefore my idea was to create a folder in Sharepoint for each customer and to share it with the customer as a guest user. So the customer has access to "his" document folder and can upload and download documents there. I can do this manually as well, but I would like to solve this programmatically via CSOM.
The programmatic creation of the folder I have managed so far. Also the file upload is no problem.
However, the release of the folder of the customer is problematic. I managed to share the folder so that the customer can log in with his Microsoft account or that the order is released "for everyone".
What I need is a personal release WITHOUT forcing an MS account. An personal link with verification code etc...
This is my code so far.
public static void CreateAndShareFolder(ClientContext context, string folderName, string userEmail)
{
var listTitle = "Dokumente";
var rootFolder = "Testfolder_ROOT/";
var folder = CreateFolder(context.Web, listTitle, rootFolder + folderName);
var users = new List<UserRoleAssignment>();
users.Add(new UserRoleAssignment()
{
UserId = userEmail,
Role = Role.Edit,
});
var serverRelativeUrl = folder.ServerRelativeUrl;
var absoluteUrl = new Uri(context.Url).GetLeftPart(UriPartial.Authority) + serverRelativeUrl;
/* User gets Email, but with "public" Sharing-Link */
//var userSharingResults = DocumentSharingManager.UpdateDocumentSharingInfo(context, absoluteUrl, users, true, true, true, null, true, true);
/* User gets Email, but needs an MS-Account to View */
var userSharingResults = DocumentSharingManager.UpdateDocumentSharingInfo(context, absoluteUrl, users, false, false, true, null, false, true);
context.ExecuteQuery();
}
// From Stackoverflow: https://stackoverflow.com/a/22010815/3062062
public static Folder CreateFolder(Web web, string listTitle, string fullFolderUrl)
{
if (string.IsNullOrEmpty(fullFolderUrl))
throw new ArgumentNullException("fullFolderUrl");
var list = web.Lists.GetByTitle(listTitle);
return CreateFolderInternal(web, list.RootFolder, fullFolderUrl);
}
private static Folder CreateFolderInternal(Web web, Folder parentFolder, string fullFolderUrl)
{
var folderUrls = fullFolderUrl.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
string folderUrl = folderUrls[0];
var curFolder = parentFolder.Folders.Add(folderUrl);
web.Context.Load(curFolder);
web.Context.ExecuteQuery();
if (folderUrls.Length > 1)
{
var subFolderUrl = string.Join("/", folderUrls, 1, folderUrls.Length - 1);
return CreateFolderInternal(web, curFolder, subFolderUrl);
}
return curFolder;
}

Sharing login session between Acumatica Screen based API and the Contract based API

How to share login session between Acumatica Screen based API and the Contract based API?
Sharing session data between Contract-Based and Screen-Based API is supported in 5.30.1672 build onwards.
In below code snippet, we are logging in via Contract Based API, retrieving session cookie and using it in Screen Based API.
string sharedCookie;
var soapClient = new DefaultSoapClient();
using (new OperationContextScope(soapClient.InnerChannel))
{
soapClient.Login("admin", "123", null, null, null);
var responseMessageProperty = (HttpResponseMessageProperty)
OperationContext.Current.IncomingMessageProperties[HttpResponseMessageProperty.Name];
sharedCookie = responseMessageProperty.Headers.Get("Set-Cookie");
}
try
{
apitest.Screen context = new apitest.Screen();
context.CookieContainer = new System.Net.CookieContainer();
context.Url = "http://localhost/AcumaticaCBWS/Soap/APITEST.asmx";
context.CookieContainer.SetCookies(new Uri(context.Url), sharedCookie);
SO301000Content salesOrdersSchema = context.SO301000GetSchema();
var commands = new Command[]
{
new Value
{
LinkedCommand = salesOrdersSchema.OrderSummary.OrderType,
Value = "SO"
},
salesOrdersSchema.OrderSummary.ServiceCommands.EveryOrderNbr,
salesOrdersSchema.OrderSummary.OrderType,
salesOrdersSchema.OrderSummary.OrderNbr,
salesOrdersSchema.OrderSummary.Description
};
var orders = context.SO301000Export(commands, null, 10, false, false);
}
finally
{
soapClient.Logout();
}
}

Search information by user on firebase

This is probably very simple ,so sorry...
I'm trying to create an application where i can create users and store informations by Firebase. There is an example here :
http://image.noelshack.com/fichiers/2015/11/1426182307-log.png
But now I want to check if the name already exists if someone wants to create a new user.
How would I go about grabbing individual user information without knowing their id , like simplelogin:54?
I've found this topic Get users by name property using Firebase but it is not the same thing because in my case I don't know the children after "Users"
Cheers,
Like Frank said, you must know something about the user to be able to look her/him up.
However, here is a general answer. I am assuming that by "name" you mean the property "identifiant" that you've created.
Suggestions
Start by looking over the Firebase Query documentation.
Short Answer
To check if a user exists by the identifiant property, you'd orderByChild("identifiant") and query for a specific user with the .equalTo("<identifient_here>").
For example, to check if a user with identifient="aaa",
var usersRef = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com/Users");
var identifient = "aaa";
usersRef.orderByChild("identifiant").equalTo(identifient).once("value", function(snapshot) {
console.log("Loaded user by identifient:",identifient,snapshot.val());
});
If instead you want to query by the key (such as simplelogin:53), you could query by using orderByKey() instead of orderByChild()... or just simply setting the ref to the user's key like so:
var userKey = 'simplelogin:53';
var userRef = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com/Users" + userKey);
userRef.once("value", function(snapshot) {
console.log("Loaded user",snapshot.val());
});
Long(er) Answer
You can handle this with a user factory (see Angular Providers documentation).
You return a promise in the factory using the $q service.
Here is the Angular API documentation for $q.
Example with UserFactory
Check out this working PLNKR example.
It's tied to one of my public Firebase instances.
I created the same simplelogin:53 user in /Users like you have.
If you search for the identifient = aaa, you'll get the right user.
The controller implementation here is for example purposes, and doesn't really do anything worth while. It's just for reference.
The Data
{
"Users" : {
"simplelogin:53" : {
"identifiant" : "aaa"
}
}
}
UserFactory
.factory('UserFactory', function($q, $firebaseObject, fbUrl){
return function(userId){
var deferred = $q.defer();
if (userId.isNotEmpty()) {
var userRef = new Firebase(fbUrl + '/Users/').orderByChild("identifiant").equalTo(userId);
userRef.once("value",
function(dataSnapshot){
if (dataSnapshot.val()) {
console.log("Loaded user",dataSnapshot.val());
deferred.resolve(dataSnapshot.val());
} else {
console.info("Couldn't find user by id",userId);
deferred.reject("No user found by identifient = '"+userId+"'");
}
},
function(error){
console.error("Error loading user",error);
deferred.reject(error);
}
);
} else {
deferred.reject("No id entered!");
}
return deferred.promise;
}
})
Controller
.controller('HomeController',function($scope, UserFactory) {
$scope.identifient = '';
var showError = function(errorMessage) {
if (errorMessage) {
showUser(false);
$scope.error = errorMessage;
} else {
delete $scope.error;
}
}
var showUser = function (userObject) {
if (userObject) {
showError(false);
$scope.user = userObject;
} else {
delete $scope.user;
}
}
$scope.loadUser = function() {
var userPromise = new UserFactory($scope.identifient);
userPromise.then(function(data){
showUser(data);
}).catch(function(error){
showError(error);
});
}
})
Template
<div ng-controller="HomeController">
<h2>Home Template</h2>
<input ng-model="identifient" placeholder="identifient"/>
<button ng-click="loadUser()">Find User</button>
<hr/>
<div ng-if="user">User: {{user}}</div>
<div ng-if="error">Error: {{error}}</div>
</div>
Hope that helps.

Resources