@@ -66,27 +66,23 @@ func (r *UserResource) Schema(ctx context.Context, req resource.SchemaRequest, r
66
66
stringplanmodifier .UseStateForUnknown (),
67
67
},
68
68
},
69
-
70
69
"username" : schema.StringAttribute {
71
70
MarkdownDescription : "Username of the user." ,
72
71
Required : true ,
73
72
},
74
73
"name" : schema.StringAttribute {
75
- Computed : true ,
76
74
MarkdownDescription : "Display name of the user. Defaults to username." ,
77
- Required : false ,
75
+ Computed : true ,
78
76
Optional : true ,
79
- // Defaulted in Create
80
77
},
81
78
"email" : schema.StringAttribute {
82
79
MarkdownDescription : "Email address of the user." ,
83
80
Required : true ,
84
81
},
85
82
"roles" : schema.SetAttribute {
86
83
MarkdownDescription : "Roles assigned to the user. Valid roles are 'owner', 'template-admin', 'user-admin', and 'auditor'." ,
87
- Required : false ,
88
- Optional : true ,
89
84
Computed : true ,
85
+ Optional : true ,
90
86
ElementType : types .StringType ,
91
87
Validators : []validator.Set {
92
88
setvalidator .ValueStringsAre (
@@ -97,24 +93,24 @@ func (r *UserResource) Schema(ctx context.Context, req resource.SchemaRequest, r
97
93
},
98
94
"login_type" : schema.StringAttribute {
99
95
MarkdownDescription : "Type of login for the user. Valid types are 'none', 'password', 'github', and 'oidc'." ,
100
- Required : false ,
101
- Optional : true ,
102
96
Computed : true ,
97
+ Optional : true ,
103
98
Validators : []validator.String {
104
99
stringvalidator .OneOf ("none" , "password" , "github" , "oidc" ),
105
100
},
106
101
Default : stringdefault .StaticString ("none" ),
102
+ PlanModifiers : []planmodifier.String {
103
+ stringplanmodifier .RequiresReplaceIfConfigured (),
104
+ },
107
105
},
108
106
"password" : schema.StringAttribute {
109
107
MarkdownDescription : "Password for the user. Required when login_type is 'password'. Passwords are saved into the state as plain text and should only be used for testing purposes." ,
110
- Required : false ,
111
108
Optional : true ,
112
109
Sensitive : true ,
113
110
},
114
111
"suspended" : schema.BoolAttribute {
115
- Computed : true ,
116
112
MarkdownDescription : "Whether the user is suspended." ,
117
- Required : false ,
113
+ Computed : true ,
118
114
Optional : true ,
119
115
Default : booldefault .StaticBool (false ),
120
116
},
@@ -164,14 +160,15 @@ func (r *UserResource) Create(ctx context.Context, req resource.CreateRequest, r
164
160
}
165
161
166
162
tflog .Trace (ctx , "creating user" )
167
- loginType := codersdk .LoginTypeNone
168
- if data .LoginType .ValueString () != "" {
169
- loginType = codersdk .LoginType (data .LoginType .ValueString ())
170
- }
171
- if loginType == codersdk .LoginTypePassword && data .Password .ValueString () == "" {
163
+ loginType := codersdk .LoginType (data .LoginType .ValueString ())
164
+ if loginType == codersdk .LoginTypePassword && data .Password .IsNull () {
172
165
resp .Diagnostics .AddError ("Data Error" , "Password is required when login_type is 'password'" )
173
166
return
174
167
}
168
+ if loginType != codersdk .LoginTypePassword && ! data .Password .IsNull () {
169
+ resp .Diagnostics .AddError ("Data Error" , "Password is only allowed when login_type is 'password'" )
170
+ return
171
+ }
175
172
user , err := client .CreateUser (ctx , codersdk.CreateUserRequest {
176
173
Email : data .Email .ValueString (),
177
174
Username : data .Username .ValueString (),
@@ -189,13 +186,13 @@ func (r *UserResource) Create(ctx context.Context, req resource.CreateRequest, r
189
186
data .ID = UUIDValue (user .ID )
190
187
191
188
tflog .Trace (ctx , "updating user profile" )
192
- name := data .Username . ValueString ()
189
+ name := data .Username
193
190
if data .Name .ValueString () != "" {
194
- name = data .Name . ValueString ()
191
+ name = data .Name
195
192
}
196
193
user , err = client .UpdateUserProfile (ctx , user .ID .String (), codersdk.UpdateUserProfileRequest {
197
194
Username : data .Username .ValueString (),
198
- Name : name ,
195
+ Name : name . ValueString () ,
199
196
})
200
197
if err != nil {
201
198
resp .Diagnostics .AddError ("Client Error" , fmt .Sprintf ("Unable to update newly created user profile, got error: %s" , err ))
@@ -290,18 +287,23 @@ func (r *UserResource) Update(ctx context.Context, req resource.UpdateRequest, r
290
287
return
291
288
}
292
289
290
+ name := data .Username
291
+ if data .Name .ValueString () != "" {
292
+ name = data .Name
293
+ }
293
294
tflog .Trace (ctx , "updating user" , map [string ]any {
294
295
"new_username" : data .Username .ValueString (),
295
- "new_name" : data . Name .ValueString (),
296
+ "new_name" : name .ValueString (),
296
297
})
297
298
_ , err = client .UpdateUserProfile (ctx , user .ID .String (), codersdk.UpdateUserProfileRequest {
298
299
Username : data .Username .ValueString (),
299
- Name : data . Name .ValueString (),
300
+ Name : name .ValueString (),
300
301
})
301
302
if err != nil {
302
303
resp .Diagnostics .AddError ("Client Error" , fmt .Sprintf ("Unable to update user profile, got error: %s" , err ))
303
304
return
304
305
}
306
+ data .Name = name
305
307
tflog .Trace (ctx , "successfully updated user profile" )
306
308
307
309
var roles []string
@@ -320,15 +322,17 @@ func (r *UserResource) Update(ctx context.Context, req resource.UpdateRequest, r
320
322
}
321
323
tflog .Trace (ctx , "successfully updated user roles" )
322
324
323
- tflog .Trace (ctx , "updating password" )
324
- err = client .UpdateUserPassword (ctx , user .ID .String (), codersdk.UpdateUserPasswordRequest {
325
- Password : data .Password .ValueString (),
326
- })
327
- if err != nil && ! strings .Contains (err .Error (), "New password cannot match old password." ) {
328
- resp .Diagnostics .AddError ("Client Error" , fmt .Sprintf ("Unable to update password, got error: %s" , err ))
329
- return
325
+ if data .LoginType .ValueString () == string (codersdk .LoginTypePassword ) && ! data .Password .IsNull () {
326
+ tflog .Trace (ctx , "updating password" )
327
+ err = client .UpdateUserPassword (ctx , user .ID .String (), codersdk.UpdateUserPasswordRequest {
328
+ Password : data .Password .ValueString (),
329
+ })
330
+ if err != nil && ! strings .Contains (err .Error (), "New password cannot match old password." ) {
331
+ resp .Diagnostics .AddError ("Client Error" , fmt .Sprintf ("Unable to update password, got error: %s" , err ))
332
+ return
333
+ }
334
+ tflog .Trace (ctx , "successfully updated password" )
330
335
}
331
- tflog .Trace (ctx , "successfully updated password" )
332
336
333
337
var statusErr error
334
338
if data .Suspended .ValueBool () {
0 commit comments