Search code examples
apostrophe-cms

Create User Profile Piece


I wanted to create a user profile piece, which joins apostrophe-user so that the admin can make public profile for specific users. I know its not recommended but I see this as the only option to have the possibility for people on this side having a public profile and be able to login and edit their profiles. Otherwise the Admin needs to change user profiles for hundreds of people and this would result in a full time job. User register is not necessary now but maybe in the future so my module should be compatible with apsotrophe-signup.

The beginning is pretty straight forward:

// lib/modules/profiles/index.js
module.exports = {
  extend: 'apostrophe-pieces',
  name: 'profile',
  label: 'Profile',
  pluralLabel: 'Profiles',
  slugPrefix: 'profile-',
  addFields: [
    {
        name: '_user',
        label: 'User',
        type: 'joinByOne',
        withType: 'apostrophe-user',
        idField: 'userId',
        withJoins: true
    }
  ]
};

This is the pieces widget:

// lib/modules/profiles-widgets/views/widget.html

{% for piece in data.widget._pieces %}
  <li class="collection-item avatar">

    {{ piece._user.username }}

    {{ piece._user.title }}

    {{ piece._user.firstName }}

    {{ piece._user.lastName }}

    {{ piece._user.email }}

    <img class="circle grey"
      src="{{ apos.attachments.url(piece._user._thumbnail.attachment, { size: data.options.size or 'one-sixth' }) }}"
      srcset="{{ apos.images.srcset(piece._user._thumbnail.attachment) }}"
      sizes="{{ '8vw' }}"
      alt="{{ piece._user._thumbnail.title }}"
    >

    {{ apos.area(piece._user, 'bio', { edit: false }) }}

  </li>
{% endfor %}

The fields _thumbnail and bio I added to apostrophe-user:

// lib/modules/apostrophe-users/index.js
module.exports = {
  beforeConstruct: function(self, options) {
      options.addFields = [
        {
          name: '_thumbnail',
          type: 'joinByOne',
          withType: 'apostrophe-image',
          label: 'Profile Picture',
          help: 'Choose profile picture',
          filters: {
            projection: {
              attachment: true,
              description: true,
              title: true
            }
          }
        },
        {
          name: 'bio',
          label: 'Biography',
          type: 'area',
          help: 'Choose Biography',
          options: {
            limit: 1,
            widgets: {
              'apostrophe-rich-text': {
                toolbar: [ 'Bold' ],
                controls: {
                  movable: false,
                  cloneable: false,
                  removable: true,
                  position: 'top-right'
                }
              }
            }
          }
        }
      ].concat(options.addFields || []);
  }
};

When logged in this works, I see all the fields defined in widget.html however if I'm logged out I see nothing. I expected this cause apostrophe-users are unpublished by default. I tried to add a published field to apostrophe-user but this didn't worked out.

// lib/modules/apostrophe-users/index.js
...

        {
          type: 'boolean',
          name: 'published',
          label: 'Published',
          def: true,
        },
...

What did I made wrong ?

As a second question I would like to know if it is possible to allow the logged in user to edit his own profile?


Solution

  • There is no direct support for using users as publicly available data in Apostrophe 2. A common workaround is to create a "Profile" piece type or something like that, then add a join to connect it to a user if that helps with organization.

    Setting adminOnly: false on the users module you could possibly configure permissions directly, but it would make security concerns around users part of your responsibilities.

    Update: Writing lib/modules/apostrophe-users/index.js in a project like this will add the published fields back to users:

    module.exports = {
      defaultRemoveFields: [],
      defaultRemoveFilters: [],
      defaultRemoveColumns: []
    };
    
    

    By default those arrays include 'published', hiding the publishing options from the UI.

    Once published they will be visible when logged out. Again, make sure to take security implications into account when doing this.