How would I add users to an IAuthRepository without allowing self-registration? Is there a way to require a certain role (e.g. admin) for the RegistrationFeature, or would it be easier to create a separate project with only the RegistrationFeature only running on localhost?
If you don't want users to be able to register themselves then maybe you don't want to enable the RegistrationFeature itself which is not registered by default.
You'll have more flexibility in just using the IAuthRepository itself in your own Service to create users.
ServiceStack's new Auth Templates shows examples of using the IAuthRepository to create Users on Startup, e.g:
if (authRepo.GetUserAuthByUserName("user#gmail.com") == null)
{
var testUser = authRepo.CreateUserAuth(new UserAuth
{
DisplayName = "Test User",
Email = "user#gmail.com",
FirstName = "Test",
LastName = "User",
}, "p#55wOrd");
}
if (authRepo.GetUserAuthByUserName("manager#gmail.com") == null)
{
var roleUser = authRepo.CreateUserAuth(new UserAuth
{
DisplayName = "Test Manager",
Email = "manager#gmail.com",
FirstName = "Test",
LastName = "Manager",
}, "p#55wOrd");
authRepo.AssignRoles(roleUser, roles:new[]{ "Manager" });
}
if (authRepo.GetUserAuthByUserName("admin#gmail.com") == null)
{
var roleUser = authRepo.CreateUserAuth(new UserAuth
{
DisplayName = "Admin User",
Email = "admin#gmail.com",
FirstName = "Admin",
LastName = "User",
}, "p#55wOrd");
authRepo.AssignRoles(roleUser, roles:new[]{ "Admin" });
}
I guess I've found out how:
typeof(RegisterService).AddAttributes(new RequiredRoleAttribute("Admin"));
More here: https://docs.servicestack.net/restricting-services
Related
I'm using the Google People API to populate the address book of my dashboard. I have a lot of contacts so the idea is to filter contacts by creating a specific group for this service. What I need is basically the possibility to query all the connections filtered on a specific group id. It seems the official API has only "list" method without the chance to query on. I'm using the client libraries for node.js and here it is my code:
const {google} = require('googleapis');
const getGoogleConnections = async (userToken) => {
const oauth2Client = new google.auth.OAuth2;
oauth2Client.setCredentials({
'access_token': userToken, //Passport session user
});
const googlePeople = await google.people({
version: 'v1',
auth: oauth2Client,
});
const params = {
resourceName: 'people/me',
pageSize: 200,
sortOrder: 'LAST_MODIFIED_DESCENDING',
personFields: ['names', 'emailAddresses', 'memberships', 'organizations'],
};
const connections = await googlePeople.people.connections.list(params);
return connections;
};
My response:
"connections": [
{
... //returning all specified personFieldsValues
"memberships": [
{
"metadata": {
"source": {
"type": "CONTACT",
"id": "id value"
}
},
"contactGroupMembership": {
"contactGroupId": "contact group id",
"contactGroupResourceName": "contactGroups/contact group id"
}
},
{
"metadata": {
"source": {
"type": "CONTACT",
"id": "metadata id "
}
},
"contactGroupMembership": {
"contactGroupId": "myContacts",
"contactGroupResourceName": "contactGroups/myContacts"
}
}
]
}
],
My response is correct and the API returns all the values but I can't find a way to filter these returned values on contact group id. Anyone tried this before?
Issue:
As was mentioned in comments by Tanaike, there is no way to filter the returned connections when calling people.connections.list (there's no optional query parameter or similar, unlike other list methods from Google APIs).
File a feature request:
I'd suggest you to request this on Issue Tracker's People component, if you think this functionality could be useful.
Workaround:
Meanwhile, what you can do is filtering the connections after they have been returned by the API. You could filter them according to the group ID the following way, using filter and some:
const connections = await googlePeople.people.connections.list(params);
const filteredConnections = connections.connections.filter(connection => {
return connection.memberships.some(membership => {
if (membership.contactGroupMembership) {
return membership.contactGroupMembership.contactGroupId === "YOUR_GROUP_ID";
} else return false;
});
});
I am using Microsoft Bot Framework. My intent is to get the user email of customers when they are chatting with Microsoft Bot on Microsoft Teams.
On my application, I am using library "botbuilder" and NodeJs language.
I have an example code:
var builder = require('botbuilder');
let inMemoryStorage = new builder.MemoryBotStorage();
var botSetting = {appId: '4c8f3u2b-c56n-4117-bc16-ec31eeb5d25c', appPassword: '4CBNO8vBGtdcGh9PoiVYottY'};
var connector = new builder.ChatConnector(botSetting);
var bot = new builder.UniversalBot(connector).set('storage', inMemoryStorage);
bot.dialog("/Debug", [
function (session, args, next) {
session.endDialog("Hello");
}
]);
var address = {
"channelId" : "msteams",
"bot" : {
"id" : "28:1b435929-3da2-46ed-8ccc-29ecb50cf350",
"name" : "taskbot-prod",
"nickname" : "taskbot-prod"
},
"serviceUrl" : "https://smba.trafficmanager.net/amer-client-ss.msg/",
"user" : {
"id" : "29:1rf-2Bm6aD0BWc-yRNDFcgOBG1-uSaEjCWtJcoR-rcU-Humz3a_RddsCKifHqYpvNSUosrRpxUnYL907Qa1ZZuw",
"name" : "John Smith"
},
"channelData" : {
"tenant" : {
"id" : "adb94d72-6cf3-4244-86ae-aa69c9f2ad43"
}
}
};
bot.beginDialog(address, "/Debug", {});
In the example code above, I already have user id (29:1rf-2Bm6aD0BWc-yRNDFcgOBG1-uSaEjCWtJcoR-rcU-Humz3a_RddsCKifHqYpvNSUosrRpxUnYL907Qa1ZZuw), but I don't know how to get user email by this id.
So, what API should I use to get the user email by id? If not API, then what MS Bot Framework Library should I use to get user email by ID?
i created a signup function with node js and firebase..here is my script.
var admin = require('./../config/firebase-admin');
var database = admin.database();
var express = require('express');
var router = express.Router();
var _ = require('underscore');
var fillable = {
// fbId: "",
firstName: "",
middleName: "",
lastName: "",
birthdate: "",
gender: "",
address: "",
email: "",
phone: "",
password: "",
imageUrl: "",
token: "",
createdAt: "",
updatedAt: "",
};
router.post('/client', (req, res) => {
var ref = database.ref('clients');
var body = _.pick(_.assign(fillable, req.body), _.keys(fillable));
body['createdAt'] = moment().format('YYYY-MM-DD HH:mm:ss');
ref.push(body);
res.json(
{
"messages": [
{"text": "You are now registered as Client."}
]
}
);
});
this works fine.... but when i use .push it auto generates the id..
now my question is is there any possibility to update the unique ID that is being generated by the .push cause what im trying to make is when the user sign up to page it will save the data to firebase. then once the user use the app and input his/her phone number for authentication the UID will be the unique ID instead of the auto generated ID?. is it possible?.
You can probably implement this as an update. Updating with a payload like:
{
'old_id': null,
'new_id': {
...
}
}
But I would highly recommend you to reconsider this design. Changing the unique IDs of entries is not a good idea in most systems. See if you can make uid a child attribute of the original entry.
If you do not like the auto generated ID, your next option is to create a unique ID by yourself and save it. However this is risky in my opinion and I see absolutely no reason to do this in your case.
Trying to attempt to change the unique ID is a bad idea, because you are destroying the data relationship (Yes I know it is not like in MySQL etc, but still, we use this ID to uniquely identify users and find related records saved in other tables).
I need to find the collection data by an single MongoDB query using Node.js. I am providing the collection below.
f_user_login:
{
"_id": {
"$oid": "5981b48654d471000459208e"
},
"email": "subhrajyoti.pradhan#oditeksolutions.com",
"password": "d0e49bcba946540cb3d5fc808870d16b",
"dob": "02-08-2017",
"created_date": "2017-08-02 11:16:21",
"updated_date": "2017-08-02 11:16:21",
"status": 1,
"token": "b85ff4c47093217587f8c7f2fff7ff86b1bcbf6a7321705871435929ee38",
"verification_id": ""
}
{
"_id": {
"$oid": "598aa189e5f78d00042f48ae"
},
"email": "subhrajyotipradhan#gmail.com",
"password": "d0e49bcba946540cb3d5fc808870d16b",
"dob": "1986-04-10",
"created_date": "2017-08-09 05:45:44",
"updated_date": "2017-08-09 05:45:44",
"status": 0,
"token": "",
"verification_id": "7ffbe3f9be82b2af84491d3e8dff4fa1a65f973d"
}
I am providing my code below.
exports.userSignin=function(req,res){
var email=req.body.email;//subhrajyotipradhan#gmail.com
var password=req.body.password;//d0e49bcba946540cb3d5fc808870d16b
var pass=mden(password);
if (email !='' && password !='') {
db.f_user_login.count({email:email,password:pass,status:1},function(err,docs){
if(docs > 0){
token=crypto.randomBytes(30).toString('hex');
db.f_user_login.update({email:email},{$set:{token:token}},function(err,doc){
db.f_user_login.find({email:email},function(error,docu){
var edata=[{"email": docu[0].email,"dob": docu[0].dob,"created_date":docu[0].created_date ,"id": docu[0]._id,"updated_date":docu[0].updated_date,"token_id":token}];
var data={"statusCode": 200,"data":edata,"message": "The user logged successfully."};
res.send(data);
})
})
}else{
console.log(email,password);
db.f_user_login.find({$or:[{email:email},{password:pass},{status:1}]},function(err,getdocs){
if (!err) {
var uemail=getdocs[0].email;
var upass=getdocs[0].password;
var ustatus=getdocs[0].status;
console.log('email,pass,status',uemail,upass,ustatus);
if (uemail != email) {
var data={"statusCode": 401,"error": "Unauthorized","message": "Invalid email id .Please provide a valid email id"};
}
if (upass != pass) {
var data={"statusCode": 401,"error": "Unauthorized","message": "Invalid Password .Please provide a valid Password"};
}
if (ustatus == 0) {
var data={"statusCode": 401,"error": "Unauthorized","message": "you have not verified your account using the link sent to your email."};
}
res.send(data);
}
})
}
})
}
}
Here my input email and password is right and I need to check the status and get this you have not verified your account using the link sent to your email. message. But unfortunately both document has same password its always checking the first document but originally I need to check the second document for validation.
It is possible using 3 three different query but here I want to operate a single query. Is this possible?
You can use below code for the entire process:
Note: Some typos or code may need to be changed. But you can use the basic idea.
if (email !='' && password !='') {
console.log(email,password);
db.f_user_login.find({$and:[{email:email},{password:pass}]},function(err,getdocs){
if (!err && /*check if the getdocs is not empty*/) {
var uemail=getdocs[0].email;
var upass=getdocs[0].password;
var ustatus=getdocs[0].status;
// update your collection from here with ID
// Remember update is work fine with id
console.log('email,pass,status',uemail,upass,ustatus);
if (ustatus === 0) {
var data={"statusCode": 401,"error": "Unauthorized","message": "you have not verified your account using the link sent to your email."};
}else if(ustatus === 1){
var data={"statusCode": 200,"data":edata,"message": "The user logged successfully."};
}
res.send(data);
}
})
}
I want to get data in nodejs application as describe bellow out put.
user.js, userProfile are the models of mongoose.
user.js
var userSchema = new Schema({
nick_name:{type:String},
email: {type: String},
password: {type: String},
is_active:{type:String,enum:['1','0'],default:"1"},
},{ collection: 'user'});
userProfile.js
var userProfileSchema = new Schema({
user_id:{type:Schema.Types.ObjectId, ref:'User'},
first_name:{type:String},
last_name:{type:String},
address:{type:String},
country:{type:String},
state:{type:String},
city:{type:String},
gender:{type:String,enum:['m','f','o'],default:"m"},
is_active:{type:String,enum:['1','0'],default:"1"},
},{ collection: 'userProfile'});
wants to get out put as follows
{
"nick_name" : "laxman",
"email" : "laxman#mailinator.com",
"first_name" : "my first name",
"last_name" : "my last name",
"address" : "my address",
"country" : "my country",
"state" : "my state",
"city" : "my city",
"gender" : "m",
}
dependencies
"express" => "version": "4.7.4",
"mongoose" => "version": "4.4.5",
"mongodb" => "version": "2.4.9",
"OS" => "ubuntu 14.04 lts 32bit",
SQL query for reference
SELECT * FROM `user`
left join `user_profile`
on user.id =user_profile.user_id
WHERE 1
The answer to this question is going to depend on how you are doing your authentication, but I will answer this question how I would achieve what you are asking.
Firstly, I would make one Schema instead of having two separate ones. Then, depends on your authentication method, I use tokens, you will pass that data to whatever you is receiving it on the client side. It would also help to know if you are using anything on the client side that handles HTTP requests or if this is just a node application.
I'll try to cover both methods in some detail.
Say you are using cookies for instance, I'm going to assume you know how to set up a session using Express, or whatever if any framework you are using on top of node, as well as assuming you know what you are doing as far as securing your passwords properly and skip straight to the api building.
Pretend this is a controller on your server side to authenticate the user on login.
var User = mongoose.model('User');
exports.login = function (req, res) {
User.findOne({email: req.body.email), function (err, user) {
if (err) {
return res.json(err);
} else if (!user) {
return res.json({message: 'User not found.'});
} else {
if (req.body.password === user.password) {
req.session.user = user;
} else {
return res.json({message: 'Invalid username or password.'});
}
}
)};
};
Of course, you want to make sure you have some middleware set up so the password is definitely not send along with the user, but that is not the matter here.
Once you have that, then any other route where you need user data is fairly simple. You make another controller like so:
exports.profile = function (req, res) {
if (req.session && req.session.user) {
User.findOne({email: req.session.user.email}, function (err, user) {
if (!user) {
res.session.reset();
res.redirect('/login');
} else {
res.locals.user = user;
res.render('/profile);
}
)};
}
};
I did the rendering on the server side, but if you are using something like Angular, you can pull that to the client side.
If you are using tokens, which I highly recommend, then the method is very similar. I will be happy to explain some of that as well.