we are making a social network using GAE, and when we are going to create user's, we need to save contact's data about facebook, twitter, etc...
This extra contact data must be administrable by an administrator, so if the administrator adds "Whatsapp", to all users must appear a field "Whatsapp" optional, and if the administrator deletes the facebook data, all users' facebook info must be deleted.
What is the best option to save this data, considering the most efficient way, for example, for get the all user's facebook, for delete all user's twitter... by an administrator?
Thanks
There are many ways to solve this problem. One would be to have a config model, such as (assuming python) ...
class Config(db.Model):
""" singleton model """
twitter = db.BooleanProperty(default=False)
facebook = db.BooleanProperty(default=False)
whatsapp = db.BooleanProperty(default=False)
And separate fields on your profile model for each social username ...
class Profile(db.Model):
name = db.StringProperty() # users name
twitter = db.StringProperty() # store twitter username here
facebook = db.StringProperty() # store facebook username here
whatsapp = db.StringProperty() # store whatsapp username here
When you render the profile to the client, check the Config class to see what social fields have been enabled, and only render those fields.
To handle the deletion, you may need to write a cron job to iterate through all profiles and delete whatever data has been disabled on the config model.
Hope this helps
You should certainly store all entities that contain a User's specific data in the User's entity group. That enables you to retrieve and manipulate those entities using ancestor queries, which perform better than non-ancestor queries.
To make the detail entities part of a User's entity group, you simply have to create them with the parent parameter. For instance:
class TwitterData(db.Model):
twitter_name = db.StringProperty
def addTwitterData(user, twitter_name):
# User is an instance of users.User
new_twitter_entity = TwitterData(parent=user)
new_twitter_entity.twitter_name = twitter_name
new_twitter_entity.put()
Now, I can get User's data like this:
twitter_accounts = TwitterData.all().ancestor(user).fetch(1000)
Also, you can use a kindless ancestor query to get all of the entities in user's entity group:
all_networks = db.Query()
all_networks.ancestor(user).fetch(1000)
# Now, ancestor has all of user's Twitter, Facebook, Myspace accounts.
One of the strengths of this approach is that it allows your users to have more than one account on any of the various services.
If the data that you need to store for the different social sites varies too much to be served by a single, simple model, you can use Expando classes to store entities that store different types of data.
Related
I have a Non-Salesforce Auth System which holds usernames and passwords for a few thousand users. I am willing to migrate these users to Salesforce and give access to these users to my Experience Cloud site. I am developing an apex REST Resource which will take username and password as arguments and create a user with that username and password with a community profile. I am planning to call this API from my Non-Salesforce system and migrate all these users. I am using Site.createExternalUser method in this API. I am getting the exception
Site.ExternalUserCreateException: [That operation is only allowed from within an active site.]
The reason I am using Site.createExternalUser is because I don't want to send the welcome email/reset password email to my users since they already have signed up successfully long ago.
I am open to any alternatives for achiving this.
Below is my code:
#RestResource(urlMapping='/createUser/*')
global with sharing class createUserRestResource {
#HttpPost
global static String doPost(){
Contact con=new Contact();
con.Firstname="First";
con.LastName= "Last";
con.Email="first.last#example.com";
con.AccountId='/Add an account Id here./';
insert con;
usr.Username= "usernameFromRequest#example.com";
usr.Alias= "alias123";
usr.Email= "first.last#example.com";
usr.FirstName= "First";
usr.IsActive= true;
usr.LastName= "Last";
usr.ProfileId='/Community User Profile Id/';
usr.EmailEncodingKey= 'ISO-8859-1';
usr.TimeZoneSidKey= 'America/Los_Angeles';
usr.LocaleSidKey= 'en_US';
usr.LanguageLocaleKey= 'en_US';
usr.ContactId = con.Id;
String userId = Site.createExternalUser(usr, con.AccountId, 'Password#1234', false);
return userId;
}
}
You can suppress sending emails out in whole org (Setup -> Deliverability) or in the Community config there will be way to not send welcome emails (your community -> Workspaces -> Administration -> Emails).
Without running on actual Site I don't think you can pull it off in one go. In theory it's simple, insert contact, then insert user. In practice depends which fields you set on the user. If it's Partner community you might be setting UserRoleId too and that's forbidden. See MIXED DML error. In Customer community you might be safe... until you decide to assign them some permission sets too.
You might need 2 separate endpoints, 1 to create contact, 1 to make user out of it. Or save the contact and then offload user creation to #future/Queueable/something else like that.
I have just started working on Django, angularjs , The issue currently i am facing is I have created a model in django as following
**class Car_Booking(models.Model):
owner = models.ForeignKey('auth.User', related_name='booking_user')
car_id=models.IntegerField(max_length=4,default=1)
extra_field1=models.CharField(max_length=100,null=True)
extra_field2=models.CharField(max_length=50,null=True)
extra_field3=models.CharField(max_length=50,null=True)**
The Serializer is as following
**class CarBookingSerializer(serializers.HyperlinkedModelSerializer):
owner = serializers.ReadOnlyField(source='owner.username')
class Meta:
model = Car_Booking
fields = ('car_id','owner','extra_field1','extra_field2','extra_field3')**
And view is as following
**class CarBookingViewSet(viewsets.ModelViewSet):
"""
This viewset automatically provides `list`, `create`, `retrieve`,
`update` and `destroy` actions.
Additionally we also provide an extra `highlight` action.
"""
queryset = Car_Booking.objects.all()
serializer_class = CarBookingSerializer
permission_classes = (permissions.AllowAny,
def perform_create(self, serializer):
serializer.save(owner=self.request.user)**
Now i developed a front end on Angularjs, the templelates i built were on the same server say localhost:8000 so when i call the view to insert the data by passing car_id, extra_field1, extra_field2 and extra_field 3 it gets saved successfully because i already get logged in and saved the user information into the cookies so i guess the Owner field is resolved automatically. Now when i call the same view from the IONIC framework on server localhost:5000(port is differnt) it give me the error, "Owner must be a user instance". I have searched a lot but can not find how to send the user authentication information, or save it accross the domains. Secondly i have tried to pass the owner_id but when i write the owner_id into the serializer it says "Owner_id is not a valid modlebase" but while calling throught the command prompt i can set the owner_id, Any Help on the following questions
***1. How can i send the username and password along the Post URL
How can i set the owner_id instead of OWNER object instance.***
Regards
So I have an app that takes a form, and sends and e-mail address to somebody, but I want a way to stick and activation URL generated by Django into that e-mail, and not have the form data commit to the database until that activation link is clicked. Is there any way to do this?
Based on the comments on my first answer, here's a reworked one more suited to your needs.
Create a model, e.g. ServiceHours, that next to the data you want to collect (hours done, supervisor_email, ...), has the following fields:
activation_key=models.CharField(_('activation key'), max_length=40, null=True, blank=True)
validated=models.BooleanField(default=False)
I'd suggest adding a post_save signal to the Model, so that whenever a new ServiceHours instance is created (by saving the form), the email to the supervisor is sent.
# Add this to your models file
# Required imports
from django.db.models.signals import post_save
from django.utils.hashcompat import sha_constructor
import random
def _create_and_send_activation_key(sender, instance, created, **kwargs):
if created: # Only do this for newly created instances.
salt = sha_constructor(str(random.random())).hexdigest()[:5]
# Set activation key based on supervisor email
instance.activation_key = sha_constructor(salt+instance.supervisor_email).hexdigest()
instance.save()
# Create email
subject = "Please validate"
# In the message, you can use the data the volunteer has entered by accessing
# the instance properties
message = "Include instance hours, volunteer's name etc\n"
# Insert the activation key & link
messsage += "Click here: %s" % (reverse("validate_hours", kwargs={'id': instance.id, 'activation_key':instance.activation_key})
# Send the mail
from django.core.mail import send_mail # Move this import to top of your file ofcourse, I've just put it here to show what module you need
send_mail(subject, message, sender, recipients)
post_save.connect(_create_and_send_activation_key, sender=ServiceHours)
Define a view to validate service hours based on an activation key
# in views.py
def validate_hours(request, id, activation_key):
# find the corresponding ServiceHours instance
service_hours = ServiceHours.objects.get(id=id, activation_key=activation_key)
service_hours.validated = True
service_hours.save()
In your urls.py, define an url to your validate_hours view:
urlpatterns += patterns('',
url(r'^validate-hours/(?P<id>[0-9]+)/(?P<activation_key>\w+)', validate_hours, name='validate_hours'),
This has all been off the top of my head, so please excuse any errors. I hope you get the gist of the process and can extend according to your exact needs.
You might want to set/unset the is_active flag on the user.
Conceptually:
When a user registers succesfully, be sure to set the flag to False;
Autogenerate a unique string that is tied to the user's ID and send the activation url via email;
In the activation view, decompose the key into the user ID and set the is_active flag to True;
In your login view, check whether the user trying to log in has is_active is True.
Then you'll be sure that users who are logged in have a confirmed email address.
The page in Django's documentation on user authentication provides all necessary information. For a sample login view, the chapter "How to log a user in" has one.
If you'd prefer to use a reusable app, django-registration might fit your needs perfectly.
(Post-reply addition:) why not commit the data to the database? The "waste" of having unactivated users residing in your database does not outweigh the effort you'd need to implement a solution that does not commit the data to the database. Moreover, it might be more than interesting to have an idea of the amount of unactivated users (and act accordingly).
So, I'm trying to build a 'blog gateway' in Drupal 7 that will let users add/edit/remove feeds from their own external sites to a collective stream for rating, comments etc.
The site should do something along the lines of:
Let the user add a URL for their feed via the registration form
Import the most recent posts from the feed upon registration (and afterwards continually).
Create a node for each item in the feed, which can be rated by other users.
Create lists from these nodes.
Okay, so Views in combination with the Feeds module can do most of this (import feeds, create nodes for each item and create lists). I've managed to allow users to import feeds 'manually' using the Feeds module.
The problems are that I can't find a way to limit the number of feeds a user can import, and I can't figure out how to make a URL from the registration form the basis of an import.
I've been trying to solve these problems using the Rules module, but with no results.
Methinks something along the lines of the Profile Blog Information module could do the trick, but it's only available for Drupal 6 and doesn't work with the Feeds module.
Any thoughts on solutions or alternatives?
I can't find a way to limit the number of feeds a user can import
If you use the default settings of the Feeds module, you should have a "Feed" content type already. So, if you want to control the number of "feeds" a user can import, http://drupal.org/project/node_limit should do the trick, I think. It'll help you set the number of nodes of the "Feed" content type that a user can create (which should be the same thing, right?)
how to make a URL from the registration form the basis of an import
Now, I'm going to suggest a custom module route here. It should do the trick but you may/may not want to add a custom module depending on the nature of your project/your level of expertise with Drupal.
Add a URL field (probably an instance of the URL field type) to the user profile. Check to allow it to be shown in the registration form. Lets say we call it feed_url.
Implement hook_user_insert() which is called when a new user is added to the site:
/**
* Implements hook_user_insert().
*/
function MY_MODULE_user_insert(&$edit, $account, $category) {
if (isset($edit['feed_url'])) {
$index = array('feed_url', LANGUAGE_NONE, 'value');
// Get the feed URL from the registration form values.
$feed_url = drupal_array_get_nested_value($edit, $index);
if (!empty($feed_url)) {
// Create a new feed on behalf of the user
_MY_MODULE_create_feed($feed_url, $account->uid);
}
}
}
/**
* Creates a new feed on behalf of a user.
*
* #param string $url
* Feed URL
* #param numeric $uid
* {users}.uid of the user for whom this feed is being created.
*/
function _MY_MODULE_create_feed($url, $uid) {
// #todo Add more validations here
$node = new stdClass();
$node->uid = $uid;
$node->type = 'feed';
$node->feeds['FeedsHTTPFetcher']['source'] = $url;
$node->language = language_default('language');
node_save($node);
}
I am quite new to this Google app engine. I am learning things every day.
I am have a forum on google app engine.
But I want is to be having private or restricted parts.
Some features should be locked for certain google account users, which are in some sort of access control list.
I plain words I can say, only those user who are in list of access can see the forum rest will be redirect to the "contact to admin" page.
As I am new I wanna know that is it something possible.
if yes, how can I achieve it ?
Thanks,
Alok
If you are using the built-in Users API, you can check users.is_current_user_admin() as an access control mechanism. Administrators can be managed via the dashboard.
If you need more granular, application-specific authorization logic, generally you would create a User model in the datastore that references the built-in UserProperty and also holds a list of roles or whatever else you need to check authorization.
To follow up Drew's reply, I use a similar system in my app, so my server code has something like the following class definition (simplified here for clarity)
class myUser(db.Model):
user = db.UserProperty(required=True)
rights = db.StringProperty(required=True, choices=set(["public", "private"]))
created = db.DateTimeProperty(auto_now_add=True)
lastaccess = db.DateTimeProperty(auto_now=True)
and then I have code like this where I handle queries
def checkUserRights(user):
q = db.GqlQuery("SELECT * from myUser WHERE user = :1", user)
u = q.get()
if not u:
# create a new 'public access' user if we haven't seen this person before
u = myUser(user=user, rights="public")
# always update the user record after the source is fetched (updates the lastaccess field)
db.put( u )
return u.rights
rights = checkUser(users.get_current_user())
if isPrivateArea and rights == "private":
....
This way I create a user for EVERY visitor, and then I have an admin interface to change the rights of selected users - you may decide, for example, to not create a record for every visitor
def checkUserRights(user):
q = db.GqlQuery("SELECT * from myUser WHERE user = :1", user)
u = q.get()
if not u:
# grant default public rights to anyone...
return "public"
# always update the user record after the source is fetched (updates the lastaccess field)
db.put( u )
return u.rights
This is, of course, on a page where the app.yaml specifies "login: required"