Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow to log system activity without a causer or a null causer #567

Closed
EMediaAndroid opened this issue Jul 19, 2019 · 8 comments · Fixed by #605
Closed

Allow to log system activity without a causer or a null causer #567

EMediaAndroid opened this issue Jul 19, 2019 · 8 comments · Fixed by #605
Labels
enhancement hacktoberfest https://hacktoberfest.digitalocean.com help wanted

Comments

@EMediaAndroid
Copy link

It's not clear from the documentation if this can be done or not.

Sometimes there can be activity triggered on events without a causer. Examples are when an action is taken by an unregistered user, a SYSTEM Cron, or a Bot.

Example log items can be:
'Project 123 was archived by the SYSTEM due to non-activity'
'GithubBot locked this thread on 23/05/2019'
'Anonymous user viewed the phone number'
etc

I think the workaround would be to create users with the names 'SYSTEM', 'Bot' etc, and hardcode that userID. Which can cause problems in production and testing environments.

Is there a better way to log such activities?

@Gummibeer
Copy link
Collaborator

Hey,

the causer columns are already nullable if this line returns null

->causedBy($this->auth->guard($this->authDriver)->user());
you won't have a causer.

If you want to log a system activity with a logged in user this could be done by creating the Activity model directly or override the logger service and change some methods.

@junaid-A-khan
Copy link

junaid-A-khan commented Jul 22, 2019

as explained by @Gummibeer.
If you would want to customize "causedBy" logic then you will need to do following steps to accomplish that:

  1. Create a new ActivityLogger class which will extend "Spatie\Activitylog\ActivityLogger" and override the "getActivity" method:

    use Spatie\Activitylog\ActivitylogServiceProvider;
    use Spatie\Activitylog\ActivityLogger as SpatieActivityLogger;
    use Spatie\Activitylog\Contracts\Activity as ActivityContract;
    
    class ActivityLogger extends SpatieActivityLogger
    {
          private $causedBy;
    
          protected function getActivity(): ActivityContract
          {
              $this->causedBy = $this->auth->guard($this->authDriver)->user();
    
              // Your logic if the causer is null
              if(empty($this->causedBy)){
                   // do something when causer is null.
               }
    
              if (! $this->activity instanceof ActivityContract) {
                  $this->activity = ActivitylogServiceProvider::getActivityModelInstance();
                 $this
                    ->useLog($this->defaultLogName)
                    ->withProperties([])
                    ->causedBy($this->causedBy);
             }
    
             return $this->activity;
            }
    }
    

2. Create a new ActivitylogServiceProvider which will extend "Spatie\Activitylog\ActivitylogServiceProvider" and register it in "config/app.php".
Add following code in register method of newly created service provider:

   use App\ActivityLogger;
   use \Spatie\Activitylog\ActivitylogServiceProvider as SpatieActivitylogServiceProvider;

   class ActivitylogServiceProvider extends SpatieActivitylogServiceProvider
   {

       public function register()
       {
           $this->app->alias (ActivityLogger::class, \Spatie\Activitylog\ActivityLogger::class );
       }
   }

This is tested so you should get no issue.

@Gummibeer
Copy link
Collaborator

@junaid-A-khan instead of the __construct() I would adjust the getActivity() method

protected function getActivity(): ActivityContract
{
if (! $this->activity instanceof ActivityContract) {
$this->activity = ActivitylogServiceProvider::getActivityModelInstance();
$this
->useLog($this->defaultLogName)
->withProperties([])
->causedBy($this->auth->guard($this->authDriver)->user());
}
return $this->activity;
}

This does set the init causer - so if you remove this line or adjust the condition when the causer is set yo have a null causer. The construct doesn't have to be executed for every activity log because it's a binded service which you could cache in a variable.

@junaid-A-khan
Copy link

@Gummibeer yes, parent construct call can be removed and I'm sorry, my bad, as I tested it on an old Laravel 5.7 witch has v2.8.
I am going to update previous answer.
Thanks

@Gummibeer
Copy link
Collaborator

Because atm it's impossible to set the causer to null and by default it's loaded from the current auth. Is an anonymous() method wanted which forces the activity to have no causer?

activity()
    ->anonymous()
    ->log('my log message');

Doing this for a whole runtime could belong to:

@shanecp
Copy link

shanecp commented Jul 24, 2019

Perhaps we can use,

activity()
    ->causedByAnonymous()
    ->log('my log message');

or

activity()
    ->causedBy('SYSTEM')
    ->log('my log message');

or

activity()
    ->causedBy(ActivityCauserInterface)
    ->log('my log message');

@Gummibeer Gummibeer added hacktoberfest https://hacktoberfest.digitalocean.com help wanted labels Sep 25, 2019
@Jhnbrn90
Copy link

Jhnbrn90 commented Oct 2, 2019

I had a look today at a possible solution introducing an AnonymousCauser model which should function as a "null object". Therefore, I would propose the following PR: #604 , though I have some doubt if this approach is suitable.

@Gummibeer
Copy link
Collaborator

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement hacktoberfest https://hacktoberfest.digitalocean.com help wanted
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants