@@ -14,6 +14,7 @@ import (
14
14
"strings"
15
15
16
16
"github.com/creativeprojects/resticprofile/calendar"
17
+ "github.com/creativeprojects/resticprofile/constants"
17
18
"howett.net/plist"
18
19
)
19
20
@@ -75,11 +76,10 @@ func (c *CalendarInterval) clone() *CalendarInterval {
75
76
76
77
// createJob creates a plist file and register it with launchd
77
78
func (j * Job ) createJob (schedules []* calendar.Event ) error {
78
- home , err := os . UserHomeDir ( )
79
- if err != nil {
80
- return err
79
+ ok := j . checkPermission ( j . config . Permission () )
80
+ if ! ok {
81
+ return errors . New ( "user is not allowed to create a system job: please restart resticprofile as root (with sudo)" )
81
82
}
82
-
83
83
name := getJobName (j .config .Title (), j .config .SubTitle ())
84
84
job := & LaunchJob {
85
85
Label : name ,
@@ -92,7 +92,11 @@ func (j *Job) createJob(schedules []*calendar.Event) error {
92
92
StartCalendarInterval : getCalendarIntervalsFromSchedules (schedules ),
93
93
}
94
94
95
- file , err := os .Create (path .Join (home , UserAgentPath , name + agentExtension ))
95
+ filename , err := getFilename (name , j .config .Permission ())
96
+ if err != nil {
97
+ return err
98
+ }
99
+ file , err := os .Create (filename )
96
100
if err != nil {
97
101
return err
98
102
}
@@ -106,7 +110,6 @@ func (j *Job) createJob(schedules []*calendar.Event) error {
106
110
}
107
111
108
112
// load the service
109
- filename := path .Join (home , UserAgentPath , name + agentExtension )
110
113
cmd := exec .Command (launchctlBin , commandLoad , filename )
111
114
cmd .Stdout = os .Stdout
112
115
cmd .Stderr = os .Stderr
@@ -120,14 +123,16 @@ func (j *Job) createJob(schedules []*calendar.Event) error {
120
123
121
124
// removeJob stops and unloads the agent from launchd, then removes the configuration file
122
125
func (j * Job ) removeJob () error {
123
- home , err := os .UserHomeDir ()
126
+ ok := j .checkPermission (j .config .Permission ())
127
+ if ! ok {
128
+ return errors .New ("user is not allowed to remove a system job: please restart resticprofile as root (with sudo)" )
129
+ }
130
+ name := getJobName (j .config .Title (), j .config .SubTitle ())
131
+ filename , err := getFilename (name , j .config .Permission ())
124
132
if err != nil {
125
133
return err
126
134
}
127
135
128
- name := getJobName (j .config .Title (), j .config .SubTitle ())
129
- filename := path .Join (home , UserAgentPath , name + agentExtension )
130
-
131
136
if _ , err := os .Stat (filename ); err == nil || os .IsExist (err ) {
132
137
// stop the service in case it's already running
133
138
stop := exec .Command (launchctlBin , commandStop , name )
@@ -173,10 +178,34 @@ func (j *Job) displayStatus(command string) error {
173
178
return err
174
179
}
175
180
181
+ func (j * Job ) checkPermission (permission string ) bool {
182
+ if permission == constants .SchedulePermissionUser {
183
+ // user mode is always available
184
+ return true
185
+ }
186
+ if os .Geteuid () == 0 {
187
+ // user has sudoed
188
+ return true
189
+ }
190
+ // last case is system (or undefined) + no sudo
191
+ return false
192
+ }
193
+
176
194
func getJobName (profileName , command string ) string {
177
195
return fmt .Sprintf ("%s.%s.%s" , namePrefix , strings .ToLower (profileName ), command )
178
196
}
179
197
198
+ func getFilename (name , permission string ) (string , error ) {
199
+ if permission == constants .SchedulePermissionSystem {
200
+ return path .Join (GlobalDaemons , name + agentExtension ), nil
201
+ }
202
+ home , err := os .UserHomeDir ()
203
+ if err != nil {
204
+ return "" , err
205
+ }
206
+ return path .Join (home , UserAgentPath , name + agentExtension ), nil
207
+ }
208
+
180
209
// getCalendarIntervalsFromSchedules converts schedules into launchd calendar events
181
210
// let's say we've setup these rules:
182
211
// Mon-Fri *-*-* *:0,30:00 = every half hour
0 commit comments