How would I go about creating my own implementation of IUserAuthRepository? - servicestack

I was working with out of the box authentication, with service stack, and it works great. So, right now, I am mocking up a user with the following lines of code, taken from ServiceStack examples:
var userRep = new InMemoryAuthRepository();
container.Register<IUserAuthRepository>(userRep);
string hash;
string salt;
new SaltedHash().GetHashAndSaltString("test", out hash, out salt);
userRep.CreateUserAuth(new UserAuth
{
Id = 1,
DisplayName = "DisplayName",
Email = "as#if.com",
UserName = "john",
FirstName = "FirstName",
LastName = "LastName",
PasswordHash = hash,
Salt = salt,
}, "test");
Is there someway I can define the fields in userRep? For example, lets say I want to have the field portalid as well as part of the UserAuth object? How would I go about doing this? Can I just modify the InMemoryAuthRepository class?

You can't change the Schema of ServiceStack's built-in UserAuth DTOs, but it does provide a few extensibility points which are explained in detail in this answer where you could use the RefId and RefIdStr fields to reference your own custom tables or add metadata in the UserAuth row by adding metadata to the Dictionary<string,string> Meta collection.

Related

Get SharePoint item from document library based on custom metadata

I am storing metadata with my documents and folders in SharePoint. This metadata includes an itemid which is a unique identifier from the system it came from. Is there a way to retrieve the item from SharePoint using Graph API by specifying the itemid in the metadata?
This query works for properties that Microsoft provides like name:
https://graph.microsoft.com/v1.0/sites/{siteid}/drive/root/children?$filter=name eq 'Z'
But if I try it with the custom property then I simply get an empty result:
https://graph.microsoft.com/v1.0/sites/{siteid}/drive/root/children?$filter=itemid eq 'Z'
Is there a way to query documents and folders with custom properties like this?
Here is the code used to update the field on the document in SharePoint using Graph API:
public FieldValueSet UpdateListItem(string siteId, string driveId, string fileItemId, Dictionary<string, object> additionalData)
{
var updateFileTagsRequest = graphClient.Sites[siteId].Drives[driveId].Items[fileItemId].ListItem.Fields.Request();
var fieldValueSet = new FieldValueSet { AdditionalData = additionalData };
var result = updateFileTagsRequest.UpdateAsync(fieldValueSet).Result;
return result;
}
The dictionary values being passed to the UpdateListItem method are strings and look like this: "ItemId", "A unique value"

Get TaskID for Case Activities

I was getting TaskID for Case Activities (Screen ID - SP203010) using Acumatica Web API. Now after upgrading it to version 6.0, I am not getting that. I have also tried different properties available but seems nothing is getting me that TaskID.
I am storing these activities into my database pulling from Acumatica Partner Portal and to avoid duplicate activities being imported, I was comparing it with TaskID.
Below is the code snippet I am using to get TaskID
SP203010WS.Screen context = new SP203010WS.Screen();
context.CookieContainer = new System.Net.CookieContainer();
context.AllowAutoRedirect = true;
context.EnableDecompression = true;
context.Timeout = 1000000;
context.Url = "https://sso.acumatica.com/Soap/SP203010.asmx";
PartnerPortalCreds loginCreds = GetCreds();
string username = loginCreds.PARTPRTUSE;
string password = loginCreds.PARTPRTPAS;
SP203010WS.LoginResult result = context.Login(username, password);
SP203010WS.Content content = context.GetSchema();
context.Clear();
string[][] export = context.Export
(
new SP203010WS.Command[]
{
new SP203010WS.Value
{
Value = currentAcumaticaCaseNo,
LinkedCommand = content.Case.CaseID
},
content.Activities.Type,
content.Activities.Summary,
new SP203010WS.Field { FieldName="Body", ObjectName="Activities"},
content.Activities.StartDate,
content.Activities.CreatedBy,
new SP203010WS.Field { FieldName="TaskID", ObjectName="Activities"},
},
null,
0, true, true
);
Let me know whether it has been moved or deprecated in newer version. What shall I be using instead of TaskID or where can I find that TaskID.
In Acumatica 6.0 table EPActivity was splitted on CRActivity, SMEmail and PMTimeActivity. Original table was renamed to Obsolete_EPActivity.
Now NoteID is the key field on all tables. SMEmail and PMTimeActivity contains RefNoteID field - foreign key from CRActivity.
You may find value pair TaskID and NoteID in table - Obsolete_EPActivity
#Krunal, as Ken mentioned, after upgrade to 6.0 value pair TaskID and NoteID is only available in the Obsolete_EPActivity table. One should use Obsolete_EPActivity table to replace obsolete TaskID integer values with actual NoteID GUIDs.
There is no way to access Obsolete_EPActivity table through Web Services. After upgrade to 6.0, Acumatica inserts new Activities only in the CRActivity table.
To avoid duplicate activities, you have to store actual NoteID GUIDs in your database instead of obsolete TaskID integer values and compare GUIDs while importing records.
For previously imported activities you will also have to replace TaskID values with actual NoteID GUIDs. Searching for CRActivity record based on CaseID, Subject and CreatedDateTime field values stored in your DB, you should find appropriate record and use its NoteID to replace legacy TaskID value.

Loading a meta table as object

I have a table in my database called users. In this table I only store user ID, username and password. Now, in another table called user_meta, I have the following columns: id, uid, meta_key, meta_value. I'm trying to find a way for Bookshelf to automatically load all records in user_meta where uid == userid, and store them as model.meta[meta_key] = meta_value. Sadly, I haven't been able to find a way to make this possible.
If it is possible at all, the 2nd step would be to also save all values in model.meta back on update / insert, inserting records where meta_key doesn't exist for that user ID yet, and updating where it does.
Try to set the associations (relations) between the models:
var User = bookshelf.Model.extend({
tableName: 'users',
meta: function() {
return this.hasMany(Meta);
}
});
var Meta = bookshelf.Model.extend({
tableName: 'user_meta',
user: function() {
return this.belongsTo(User);
}
});
http://bookshelfjs.org/#one-to-many

Must a new Document in MongoDB be exactly the same as the Schema?

I am facing problems in the creation of new Documents in MongoDB using Mongoose.
Must the new Documents be exactly the same as the Schemas?
I mean I have the following Schema:
ar userSchema = new Schema({
userID: Number,
userName: String,
userEmail: String,
teams:Array,
fbUID: String,
googleUID: String,
twitter: String
});
But to create a new user Document I dont have all the fields, so my Document will not contain all the field as the Schema above.
For example, I am adding a new document based on the Schema above. My Doc is:
var users = mongoose.model('users',userSchema);
var user = new users({
userID: id, //give the id of the next user in Dbase
userName: userName,
userEmail: 'userEmail',
teams:[],
fbUID: '1234'
});
user.save(function(err, user){
if(err) return console.error(err);
log.d("user salved", user);
});
So, I dont have all the fields, and I could not save any Doc so far.
Does it matter if I don't have all the fields in the Schema in the new Document?
UPDATE:
and the second problem is that I am getting one of these :
fbUID,
googleUID,
twitter
through a function, and I don't know which of those I am receiving, so I am trying to save the Document this way:
function salveUser(userName, socialMediaType, socialMediaID){
var id;
users.count(function(err, count){
if(err){
log.d("Err in counting files")
}
id = count;
});
var user = new users({
userID: id, //give the id of the next user in Dbase
userName: userName,
userEmail: 'userEmail',
teams:[],
socialMediaType : socialMediaID
});
user.save(function(err, user){
if(err) return console.error(err);
log.d("user salved", user);
});
currentSession = sessionOBJ.login(id, socialMediaID);
return currentSession;
}
}
That is why I would like to know if Mongoose switch the key in the Document by the word I am receiving in my function or if it uses the exactly word I am putting there, in this case "socialMediaType".
Does someone know?
Answering your main question: no, new Documents shouldn't be exactly the same as the Schemas.
Actually, none of the document's fields defined in its schema are required in order to save it, unless you explicitly marked some of them as required.
But you made several mistakes in your salveUser function.
First, your id = count assignment will take place long after user document will be created and saved, because users.count is asynchronous. It means that userID in your example will always be udefined.
To fix it you should wait for users.count to finish before trying to use it's results:
users.count(function(err, count){
if(err){
return log.d("Err in counting files")
}
var user = new users({
userID: count, //give the id of the next user in Dbase
userName: userName
/* other fields */
});
user.save(/* your callback */);
});
Second, it looks like you're trying to assign a value socialMediaID to a field with a name equal to socialMediaType value. But you can't do it the way you're trying ti do it. So, instead of setting fbUID/googleUID field you're trying to set an unexisting socialMediaType field.
To fix it you should use [] assignment:
var user = new users({
userID: id, //give the id of the next user in Dbase
userName: userName,
userEmail: 'userEmail'
});
user[socialMediaType] = socialMediaID;
Since you don't have a unique index on userID field an since MongoDB automatically assigns an unique _id to all documents, you should be able to successfully .save() your document.
But in your question you said that you're unable to do it, meaning you have some other problem in your code. Please, post an exact exception you're getting from mongoose in .save() callback.
It looks like you're code is fine as Leonid said in the comments
I would try saving a user with all direct values to rule out any variable not being set....
So try this:
var user = new users({
userID: 11, //give the id of the next user in Dbase
userName: 'John',
userEmail: 'John#john.com',
teams:['Blue', 'Green'],
fbUID: '1234'
});
If that works then the problem is probably that the id or userName variables haven't been set before actually hitting this message.
You don't have to put values for all fields just because they are in the model.
Best of luck!

Redis, Node.JS and an Unique ID

What is the proper way to handle unique identifiers with Node.JS and Redis? I'm looking to make the switch from MongoDB/Mongoose to Redis. There I create a Document which gets a _id field. I can use that in other Documents, to link back to them. Then I can use findByID() to retrieve the document.
I'd like to accomplish the same thing in Redis.
For simplicity, let's imagine you have two types of objects in your system: users and widgets. Each of these objects will be stored in Redis as hashes. Below are the fields that each of the object types will have in their hashes:
user
id
name
parent (which user is responsible for this user in the system)
widget
id
name
owner (which user owns this widget)
The parent field of user and the owner field of widget will act like foreign keys that reference some other object by that object's ID.
With this configuration, you need a couple of other keys in your system: user:id and widget:id. These will be used as auto increment values of the user and widget IDs. Whenever new user or widget is added to the system, you will run the INCR command:
INCR user:id # new user ID
INCR widget:id # new widget ID
You will then use the returned INCR value as the primary key for the object. Here is some pseudo-code for adding a new user:
var newUserId = redis('INCR')
var newUserKey = 'user:' + newUserId
redis('HMSET', [newUserKey,
'id', newUserId,
'name', username,
'parent', parentUserId
])
You can see how the above code could be tweaked slightly for adding a new widget.
Let's say that someone requests widget #55 from your system. First we will fetch the widget with that ID, then we will fetch the widget's owner by ID. Below is the pseudo-code for this:
var widgetId = req.params.id // 55
var widgetKey = 'widget:' + widgetId
var widgetObject = redis('HGETALL', [widgetKey])
var userKey = 'user:' + widgetObject.owner
var userObject = redis('HGETALL', [userKey])
// Do something with widgetObject and userObject

Resources