pub struct User { /* private fields */ }Expand description
A user account (User).
Obtained from Engine::new_user,
Engine::get_user, or
Engine::current_user.
A user object built in memory is not part of the station until it is written to the users file; creating and configuring one here changes nothing on disk.
Effective privileges usually come from the groups a user belongs to rather
than from the user directly, which is why
has_privilege answers for the user and their
groups, while privileges exposes only what is set on
the user itself.
Implementations§
Source§impl User
impl User
Sourcepub fn login_name(&self) -> Result<String, Error>
pub fn login_name(&self) -> Result<String, Error>
Examples found in repository?
29fn main() -> Result<(), rs_teststand::Error> {
30 let engine = Engine::new()?;
31
32 // Passing no profile means the user inherits nothing.
33 let user = engine.new_user(None)?;
34 user.set_login_name("operator1")?;
35 user.set_full_name("Test Operator")?;
36 user.set_password("ts-secret")?;
37
38 println!("User: {} ({})", user.login_name()?, user.full_name()?);
39
40 // Check a credential without handling the stored value.
41 println!(
42 " password 'ts-secret' valid: {}",
43 user.validate_password("ts-secret")?
44 );
45 println!(
46 " password 'wrong' valid: {}",
47 user.validate_password("wrong")?
48 );
49
50 println!(" privilege checks:");
51 report_privileges(
52 &user,
53 &[
54 UserPrivilege::Operate,
55 UserPrivilege::Execute,
56 UserPrivilege::Develop,
57 UserPrivilege::Debug,
58 UserPrivilege::EditUsers,
59 ],
60 )?;
61
62 // A privilege can also be named by its full path, which is how a leaf
63 // inside a category is reached.
64 println!(
65 " Debug.RunSelectedTests: {}",
66 user.has_privilege_named("Debug.RunSelectedTests")?
67 );
68
69 // The privilege tree is nested: categories hold the individual rights.
70 let privileges = user.privileges()?;
71 let count = privileges.get_num_sub_properties("")?;
72 println!(" privilege tree ({count} categories):");
73 for index in 0..count {
74 let name = privileges.get_nth_sub_property_name("", index, 0)?;
75 let members = privileges
76 .get_property_object(&name, 0)?
77 .get_num_sub_properties("")?;
78 println!(" {name:<12} {members} member(s)");
79 }
80
81 // The station itself, read-only.
82 println!("\nStation:");
83 match engine.current_user()? {
84 Some(current) => println!(" logged in as {}", current.login_name()?),
85 None => println!(" nobody logged in (usual when login is not required)"),
86 }
87 println!(
88 " is 'operator1' a real account here? {}",
89 engine.user_name_exists("operator1")?
90 );
91
92 // Where accounts actually live. Everything above this point exists only in
93 // memory: `new_user` builds a User, it does not enrol one. A user becomes
94 // part of the station when it is inserted into this file's list and the
95 // file is written.
96 let users_file = engine.users_file()?;
97 let file = users_file.as_property_object_file()?;
98 println!(
99 "
100Users file:"
101 );
102 println!(" path {}", file.path()?);
103 println!(
104 " users {}",
105 users_file.user_list()?.get_num_elements()?
106 );
107 println!(
108 " groups {}",
109 users_file.user_group_list()?.get_num_elements()?
110 );
111 println!(
112 " profiles {}",
113 users_file.user_profile_list()?.get_num_elements()?
114 );
115
116 // Deliberately not run: it would edit the station this example is reading.
117 // The two calls a host makes to enrol the user built above are
118 //
119 // users_file.user_list()?.set_num_elements(count + 1, 0)?; // then fill
120 // file.save_file_if_modified(false)?; // then write
121 //
122 // `false` matters: with `true` the engine puts a save dialog on screen, and
123 // a host with no operator would wait for an answer that never comes.
124 println!(
125 "
126 (this example does not write; enrolling a user would alter the station)"
127 );
128
129 Ok(())
130}Sourcepub fn set_login_name(&self, name: &str) -> Result<(), Error>
pub fn set_login_name(&self, name: &str) -> Result<(), Error>
Examples found in repository?
29fn main() -> Result<(), rs_teststand::Error> {
30 let engine = Engine::new()?;
31
32 // Passing no profile means the user inherits nothing.
33 let user = engine.new_user(None)?;
34 user.set_login_name("operator1")?;
35 user.set_full_name("Test Operator")?;
36 user.set_password("ts-secret")?;
37
38 println!("User: {} ({})", user.login_name()?, user.full_name()?);
39
40 // Check a credential without handling the stored value.
41 println!(
42 " password 'ts-secret' valid: {}",
43 user.validate_password("ts-secret")?
44 );
45 println!(
46 " password 'wrong' valid: {}",
47 user.validate_password("wrong")?
48 );
49
50 println!(" privilege checks:");
51 report_privileges(
52 &user,
53 &[
54 UserPrivilege::Operate,
55 UserPrivilege::Execute,
56 UserPrivilege::Develop,
57 UserPrivilege::Debug,
58 UserPrivilege::EditUsers,
59 ],
60 )?;
61
62 // A privilege can also be named by its full path, which is how a leaf
63 // inside a category is reached.
64 println!(
65 " Debug.RunSelectedTests: {}",
66 user.has_privilege_named("Debug.RunSelectedTests")?
67 );
68
69 // The privilege tree is nested: categories hold the individual rights.
70 let privileges = user.privileges()?;
71 let count = privileges.get_num_sub_properties("")?;
72 println!(" privilege tree ({count} categories):");
73 for index in 0..count {
74 let name = privileges.get_nth_sub_property_name("", index, 0)?;
75 let members = privileges
76 .get_property_object(&name, 0)?
77 .get_num_sub_properties("")?;
78 println!(" {name:<12} {members} member(s)");
79 }
80
81 // The station itself, read-only.
82 println!("\nStation:");
83 match engine.current_user()? {
84 Some(current) => println!(" logged in as {}", current.login_name()?),
85 None => println!(" nobody logged in (usual when login is not required)"),
86 }
87 println!(
88 " is 'operator1' a real account here? {}",
89 engine.user_name_exists("operator1")?
90 );
91
92 // Where accounts actually live. Everything above this point exists only in
93 // memory: `new_user` builds a User, it does not enrol one. A user becomes
94 // part of the station when it is inserted into this file's list and the
95 // file is written.
96 let users_file = engine.users_file()?;
97 let file = users_file.as_property_object_file()?;
98 println!(
99 "
100Users file:"
101 );
102 println!(" path {}", file.path()?);
103 println!(
104 " users {}",
105 users_file.user_list()?.get_num_elements()?
106 );
107 println!(
108 " groups {}",
109 users_file.user_group_list()?.get_num_elements()?
110 );
111 println!(
112 " profiles {}",
113 users_file.user_profile_list()?.get_num_elements()?
114 );
115
116 // Deliberately not run: it would edit the station this example is reading.
117 // The two calls a host makes to enrol the user built above are
118 //
119 // users_file.user_list()?.set_num_elements(count + 1, 0)?; // then fill
120 // file.save_file_if_modified(false)?; // then write
121 //
122 // `false` matters: with `true` the engine puts a save dialog on screen, and
123 // a host with no operator would wait for an answer that never comes.
124 println!(
125 "
126 (this example does not write; enrolling a user would alter the station)"
127 );
128
129 Ok(())
130}Sourcepub fn full_name(&self) -> Result<String, Error>
pub fn full_name(&self) -> Result<String, Error>
The display name (User.FullName).
§Errors
Error if the COM call fails or returns an unexpected type.
Examples found in repository?
29fn main() -> Result<(), rs_teststand::Error> {
30 let engine = Engine::new()?;
31
32 // Passing no profile means the user inherits nothing.
33 let user = engine.new_user(None)?;
34 user.set_login_name("operator1")?;
35 user.set_full_name("Test Operator")?;
36 user.set_password("ts-secret")?;
37
38 println!("User: {} ({})", user.login_name()?, user.full_name()?);
39
40 // Check a credential without handling the stored value.
41 println!(
42 " password 'ts-secret' valid: {}",
43 user.validate_password("ts-secret")?
44 );
45 println!(
46 " password 'wrong' valid: {}",
47 user.validate_password("wrong")?
48 );
49
50 println!(" privilege checks:");
51 report_privileges(
52 &user,
53 &[
54 UserPrivilege::Operate,
55 UserPrivilege::Execute,
56 UserPrivilege::Develop,
57 UserPrivilege::Debug,
58 UserPrivilege::EditUsers,
59 ],
60 )?;
61
62 // A privilege can also be named by its full path, which is how a leaf
63 // inside a category is reached.
64 println!(
65 " Debug.RunSelectedTests: {}",
66 user.has_privilege_named("Debug.RunSelectedTests")?
67 );
68
69 // The privilege tree is nested: categories hold the individual rights.
70 let privileges = user.privileges()?;
71 let count = privileges.get_num_sub_properties("")?;
72 println!(" privilege tree ({count} categories):");
73 for index in 0..count {
74 let name = privileges.get_nth_sub_property_name("", index, 0)?;
75 let members = privileges
76 .get_property_object(&name, 0)?
77 .get_num_sub_properties("")?;
78 println!(" {name:<12} {members} member(s)");
79 }
80
81 // The station itself, read-only.
82 println!("\nStation:");
83 match engine.current_user()? {
84 Some(current) => println!(" logged in as {}", current.login_name()?),
85 None => println!(" nobody logged in (usual when login is not required)"),
86 }
87 println!(
88 " is 'operator1' a real account here? {}",
89 engine.user_name_exists("operator1")?
90 );
91
92 // Where accounts actually live. Everything above this point exists only in
93 // memory: `new_user` builds a User, it does not enrol one. A user becomes
94 // part of the station when it is inserted into this file's list and the
95 // file is written.
96 let users_file = engine.users_file()?;
97 let file = users_file.as_property_object_file()?;
98 println!(
99 "
100Users file:"
101 );
102 println!(" path {}", file.path()?);
103 println!(
104 " users {}",
105 users_file.user_list()?.get_num_elements()?
106 );
107 println!(
108 " groups {}",
109 users_file.user_group_list()?.get_num_elements()?
110 );
111 println!(
112 " profiles {}",
113 users_file.user_profile_list()?.get_num_elements()?
114 );
115
116 // Deliberately not run: it would edit the station this example is reading.
117 // The two calls a host makes to enrol the user built above are
118 //
119 // users_file.user_list()?.set_num_elements(count + 1, 0)?; // then fill
120 // file.save_file_if_modified(false)?; // then write
121 //
122 // `false` matters: with `true` the engine puts a save dialog on screen, and
123 // a host with no operator would wait for an answer that never comes.
124 println!(
125 "
126 (this example does not write; enrolling a user would alter the station)"
127 );
128
129 Ok(())
130}Sourcepub fn set_full_name(&self, name: &str) -> Result<(), Error>
pub fn set_full_name(&self, name: &str) -> Result<(), Error>
Examples found in repository?
29fn main() -> Result<(), rs_teststand::Error> {
30 let engine = Engine::new()?;
31
32 // Passing no profile means the user inherits nothing.
33 let user = engine.new_user(None)?;
34 user.set_login_name("operator1")?;
35 user.set_full_name("Test Operator")?;
36 user.set_password("ts-secret")?;
37
38 println!("User: {} ({})", user.login_name()?, user.full_name()?);
39
40 // Check a credential without handling the stored value.
41 println!(
42 " password 'ts-secret' valid: {}",
43 user.validate_password("ts-secret")?
44 );
45 println!(
46 " password 'wrong' valid: {}",
47 user.validate_password("wrong")?
48 );
49
50 println!(" privilege checks:");
51 report_privileges(
52 &user,
53 &[
54 UserPrivilege::Operate,
55 UserPrivilege::Execute,
56 UserPrivilege::Develop,
57 UserPrivilege::Debug,
58 UserPrivilege::EditUsers,
59 ],
60 )?;
61
62 // A privilege can also be named by its full path, which is how a leaf
63 // inside a category is reached.
64 println!(
65 " Debug.RunSelectedTests: {}",
66 user.has_privilege_named("Debug.RunSelectedTests")?
67 );
68
69 // The privilege tree is nested: categories hold the individual rights.
70 let privileges = user.privileges()?;
71 let count = privileges.get_num_sub_properties("")?;
72 println!(" privilege tree ({count} categories):");
73 for index in 0..count {
74 let name = privileges.get_nth_sub_property_name("", index, 0)?;
75 let members = privileges
76 .get_property_object(&name, 0)?
77 .get_num_sub_properties("")?;
78 println!(" {name:<12} {members} member(s)");
79 }
80
81 // The station itself, read-only.
82 println!("\nStation:");
83 match engine.current_user()? {
84 Some(current) => println!(" logged in as {}", current.login_name()?),
85 None => println!(" nobody logged in (usual when login is not required)"),
86 }
87 println!(
88 " is 'operator1' a real account here? {}",
89 engine.user_name_exists("operator1")?
90 );
91
92 // Where accounts actually live. Everything above this point exists only in
93 // memory: `new_user` builds a User, it does not enrol one. A user becomes
94 // part of the station when it is inserted into this file's list and the
95 // file is written.
96 let users_file = engine.users_file()?;
97 let file = users_file.as_property_object_file()?;
98 println!(
99 "
100Users file:"
101 );
102 println!(" path {}", file.path()?);
103 println!(
104 " users {}",
105 users_file.user_list()?.get_num_elements()?
106 );
107 println!(
108 " groups {}",
109 users_file.user_group_list()?.get_num_elements()?
110 );
111 println!(
112 " profiles {}",
113 users_file.user_profile_list()?.get_num_elements()?
114 );
115
116 // Deliberately not run: it would edit the station this example is reading.
117 // The two calls a host makes to enrol the user built above are
118 //
119 // users_file.user_list()?.set_num_elements(count + 1, 0)?; // then fill
120 // file.save_file_if_modified(false)?; // then write
121 //
122 // `false` matters: with `true` the engine puts a save dialog on screen, and
123 // a host with no operator would wait for an answer that never comes.
124 println!(
125 "
126 (this example does not write; enrolling a user would alter the station)"
127 );
128
129 Ok(())
130}Sourcepub fn set_password(&self, password: &str) -> Result<(), Error>
pub fn set_password(&self, password: &str) -> Result<(), Error>
Examples found in repository?
29fn main() -> Result<(), rs_teststand::Error> {
30 let engine = Engine::new()?;
31
32 // Passing no profile means the user inherits nothing.
33 let user = engine.new_user(None)?;
34 user.set_login_name("operator1")?;
35 user.set_full_name("Test Operator")?;
36 user.set_password("ts-secret")?;
37
38 println!("User: {} ({})", user.login_name()?, user.full_name()?);
39
40 // Check a credential without handling the stored value.
41 println!(
42 " password 'ts-secret' valid: {}",
43 user.validate_password("ts-secret")?
44 );
45 println!(
46 " password 'wrong' valid: {}",
47 user.validate_password("wrong")?
48 );
49
50 println!(" privilege checks:");
51 report_privileges(
52 &user,
53 &[
54 UserPrivilege::Operate,
55 UserPrivilege::Execute,
56 UserPrivilege::Develop,
57 UserPrivilege::Debug,
58 UserPrivilege::EditUsers,
59 ],
60 )?;
61
62 // A privilege can also be named by its full path, which is how a leaf
63 // inside a category is reached.
64 println!(
65 " Debug.RunSelectedTests: {}",
66 user.has_privilege_named("Debug.RunSelectedTests")?
67 );
68
69 // The privilege tree is nested: categories hold the individual rights.
70 let privileges = user.privileges()?;
71 let count = privileges.get_num_sub_properties("")?;
72 println!(" privilege tree ({count} categories):");
73 for index in 0..count {
74 let name = privileges.get_nth_sub_property_name("", index, 0)?;
75 let members = privileges
76 .get_property_object(&name, 0)?
77 .get_num_sub_properties("")?;
78 println!(" {name:<12} {members} member(s)");
79 }
80
81 // The station itself, read-only.
82 println!("\nStation:");
83 match engine.current_user()? {
84 Some(current) => println!(" logged in as {}", current.login_name()?),
85 None => println!(" nobody logged in (usual when login is not required)"),
86 }
87 println!(
88 " is 'operator1' a real account here? {}",
89 engine.user_name_exists("operator1")?
90 );
91
92 // Where accounts actually live. Everything above this point exists only in
93 // memory: `new_user` builds a User, it does not enrol one. A user becomes
94 // part of the station when it is inserted into this file's list and the
95 // file is written.
96 let users_file = engine.users_file()?;
97 let file = users_file.as_property_object_file()?;
98 println!(
99 "
100Users file:"
101 );
102 println!(" path {}", file.path()?);
103 println!(
104 " users {}",
105 users_file.user_list()?.get_num_elements()?
106 );
107 println!(
108 " groups {}",
109 users_file.user_group_list()?.get_num_elements()?
110 );
111 println!(
112 " profiles {}",
113 users_file.user_profile_list()?.get_num_elements()?
114 );
115
116 // Deliberately not run: it would edit the station this example is reading.
117 // The two calls a host makes to enrol the user built above are
118 //
119 // users_file.user_list()?.set_num_elements(count + 1, 0)?; // then fill
120 // file.save_file_if_modified(false)?; // then write
121 //
122 // `false` matters: with `true` the engine puts a save dialog on screen, and
123 // a host with no operator would wait for an answer that never comes.
124 println!(
125 "
126 (this example does not write; enrolling a user would alter the station)"
127 );
128
129 Ok(())
130}Sourcepub fn password(&self) -> Result<String, Error>
pub fn password(&self) -> Result<String, Error>
Reads the stored password field (User.Password).
Prefer validate_password for checking a
credential: it compares without the caller handling the stored value.
§Errors
Error if the COM call fails or returns an unexpected type.
Sourcepub fn validate_password(&self, password: &str) -> Result<bool, Error>
pub fn validate_password(&self, password: &str) -> Result<bool, Error>
Whether password matches this user’s (User.ValidatePassword).
§Errors
Error if the COM call fails or returns an unexpected type.
Examples found in repository?
29fn main() -> Result<(), rs_teststand::Error> {
30 let engine = Engine::new()?;
31
32 // Passing no profile means the user inherits nothing.
33 let user = engine.new_user(None)?;
34 user.set_login_name("operator1")?;
35 user.set_full_name("Test Operator")?;
36 user.set_password("ts-secret")?;
37
38 println!("User: {} ({})", user.login_name()?, user.full_name()?);
39
40 // Check a credential without handling the stored value.
41 println!(
42 " password 'ts-secret' valid: {}",
43 user.validate_password("ts-secret")?
44 );
45 println!(
46 " password 'wrong' valid: {}",
47 user.validate_password("wrong")?
48 );
49
50 println!(" privilege checks:");
51 report_privileges(
52 &user,
53 &[
54 UserPrivilege::Operate,
55 UserPrivilege::Execute,
56 UserPrivilege::Develop,
57 UserPrivilege::Debug,
58 UserPrivilege::EditUsers,
59 ],
60 )?;
61
62 // A privilege can also be named by its full path, which is how a leaf
63 // inside a category is reached.
64 println!(
65 " Debug.RunSelectedTests: {}",
66 user.has_privilege_named("Debug.RunSelectedTests")?
67 );
68
69 // The privilege tree is nested: categories hold the individual rights.
70 let privileges = user.privileges()?;
71 let count = privileges.get_num_sub_properties("")?;
72 println!(" privilege tree ({count} categories):");
73 for index in 0..count {
74 let name = privileges.get_nth_sub_property_name("", index, 0)?;
75 let members = privileges
76 .get_property_object(&name, 0)?
77 .get_num_sub_properties("")?;
78 println!(" {name:<12} {members} member(s)");
79 }
80
81 // The station itself, read-only.
82 println!("\nStation:");
83 match engine.current_user()? {
84 Some(current) => println!(" logged in as {}", current.login_name()?),
85 None => println!(" nobody logged in (usual when login is not required)"),
86 }
87 println!(
88 " is 'operator1' a real account here? {}",
89 engine.user_name_exists("operator1")?
90 );
91
92 // Where accounts actually live. Everything above this point exists only in
93 // memory: `new_user` builds a User, it does not enrol one. A user becomes
94 // part of the station when it is inserted into this file's list and the
95 // file is written.
96 let users_file = engine.users_file()?;
97 let file = users_file.as_property_object_file()?;
98 println!(
99 "
100Users file:"
101 );
102 println!(" path {}", file.path()?);
103 println!(
104 " users {}",
105 users_file.user_list()?.get_num_elements()?
106 );
107 println!(
108 " groups {}",
109 users_file.user_group_list()?.get_num_elements()?
110 );
111 println!(
112 " profiles {}",
113 users_file.user_profile_list()?.get_num_elements()?
114 );
115
116 // Deliberately not run: it would edit the station this example is reading.
117 // The two calls a host makes to enrol the user built above are
118 //
119 // users_file.user_list()?.set_num_elements(count + 1, 0)?; // then fill
120 // file.save_file_if_modified(false)?; // then write
121 //
122 // `false` matters: with `true` the engine puts a save dialog on screen, and
123 // a host with no operator would wait for an answer that never comes.
124 println!(
125 "
126 (this example does not write; enrolling a user would alter the station)"
127 );
128
129 Ok(())
130}Sourcepub fn has_privilege(&self, privilege: UserPrivilege) -> Result<bool, Error>
pub fn has_privilege(&self, privilege: UserPrivilege) -> Result<bool, Error>
Sourcepub fn has_privilege_named(&self, privilege: &str) -> Result<bool, Error>
pub fn has_privilege_named(&self, privilege: &str) -> Result<bool, Error>
Whether the user holds a privilege named by string
(User.HasPrivilege).
Takes either a base name or a full path such as
Debug.RunSelectedTests. Prefer
has_privilege for the built-in set; this exists
for custom privileges, which no enum can enumerate.
§Errors
Error if the COM call fails or returns an unexpected type.
Examples found in repository?
29fn main() -> Result<(), rs_teststand::Error> {
30 let engine = Engine::new()?;
31
32 // Passing no profile means the user inherits nothing.
33 let user = engine.new_user(None)?;
34 user.set_login_name("operator1")?;
35 user.set_full_name("Test Operator")?;
36 user.set_password("ts-secret")?;
37
38 println!("User: {} ({})", user.login_name()?, user.full_name()?);
39
40 // Check a credential without handling the stored value.
41 println!(
42 " password 'ts-secret' valid: {}",
43 user.validate_password("ts-secret")?
44 );
45 println!(
46 " password 'wrong' valid: {}",
47 user.validate_password("wrong")?
48 );
49
50 println!(" privilege checks:");
51 report_privileges(
52 &user,
53 &[
54 UserPrivilege::Operate,
55 UserPrivilege::Execute,
56 UserPrivilege::Develop,
57 UserPrivilege::Debug,
58 UserPrivilege::EditUsers,
59 ],
60 )?;
61
62 // A privilege can also be named by its full path, which is how a leaf
63 // inside a category is reached.
64 println!(
65 " Debug.RunSelectedTests: {}",
66 user.has_privilege_named("Debug.RunSelectedTests")?
67 );
68
69 // The privilege tree is nested: categories hold the individual rights.
70 let privileges = user.privileges()?;
71 let count = privileges.get_num_sub_properties("")?;
72 println!(" privilege tree ({count} categories):");
73 for index in 0..count {
74 let name = privileges.get_nth_sub_property_name("", index, 0)?;
75 let members = privileges
76 .get_property_object(&name, 0)?
77 .get_num_sub_properties("")?;
78 println!(" {name:<12} {members} member(s)");
79 }
80
81 // The station itself, read-only.
82 println!("\nStation:");
83 match engine.current_user()? {
84 Some(current) => println!(" logged in as {}", current.login_name()?),
85 None => println!(" nobody logged in (usual when login is not required)"),
86 }
87 println!(
88 " is 'operator1' a real account here? {}",
89 engine.user_name_exists("operator1")?
90 );
91
92 // Where accounts actually live. Everything above this point exists only in
93 // memory: `new_user` builds a User, it does not enrol one. A user becomes
94 // part of the station when it is inserted into this file's list and the
95 // file is written.
96 let users_file = engine.users_file()?;
97 let file = users_file.as_property_object_file()?;
98 println!(
99 "
100Users file:"
101 );
102 println!(" path {}", file.path()?);
103 println!(
104 " users {}",
105 users_file.user_list()?.get_num_elements()?
106 );
107 println!(
108 " groups {}",
109 users_file.user_group_list()?.get_num_elements()?
110 );
111 println!(
112 " profiles {}",
113 users_file.user_profile_list()?.get_num_elements()?
114 );
115
116 // Deliberately not run: it would edit the station this example is reading.
117 // The two calls a host makes to enrol the user built above are
118 //
119 // users_file.user_list()?.set_num_elements(count + 1, 0)?; // then fill
120 // file.save_file_if_modified(false)?; // then write
121 //
122 // `false` matters: with `true` the engine puts a save dialog on screen, and
123 // a host with no operator would wait for an answer that never comes.
124 println!(
125 "
126 (this example does not write; enrolling a user would alter the station)"
127 );
128
129 Ok(())
130}Sourcepub fn privileges(&self) -> Result<PropertyObject, Error>
pub fn privileges(&self) -> Result<PropertyObject, Error>
The privilege settings held on the user itself (User.Privileges).
This is not the answer to “can this user do X”, group membership is not
reflected here. Use has_privilege for that.
§Errors
Error if the COM call fails or returns an unexpected type.
Examples found in repository?
29fn main() -> Result<(), rs_teststand::Error> {
30 let engine = Engine::new()?;
31
32 // Passing no profile means the user inherits nothing.
33 let user = engine.new_user(None)?;
34 user.set_login_name("operator1")?;
35 user.set_full_name("Test Operator")?;
36 user.set_password("ts-secret")?;
37
38 println!("User: {} ({})", user.login_name()?, user.full_name()?);
39
40 // Check a credential without handling the stored value.
41 println!(
42 " password 'ts-secret' valid: {}",
43 user.validate_password("ts-secret")?
44 );
45 println!(
46 " password 'wrong' valid: {}",
47 user.validate_password("wrong")?
48 );
49
50 println!(" privilege checks:");
51 report_privileges(
52 &user,
53 &[
54 UserPrivilege::Operate,
55 UserPrivilege::Execute,
56 UserPrivilege::Develop,
57 UserPrivilege::Debug,
58 UserPrivilege::EditUsers,
59 ],
60 )?;
61
62 // A privilege can also be named by its full path, which is how a leaf
63 // inside a category is reached.
64 println!(
65 " Debug.RunSelectedTests: {}",
66 user.has_privilege_named("Debug.RunSelectedTests")?
67 );
68
69 // The privilege tree is nested: categories hold the individual rights.
70 let privileges = user.privileges()?;
71 let count = privileges.get_num_sub_properties("")?;
72 println!(" privilege tree ({count} categories):");
73 for index in 0..count {
74 let name = privileges.get_nth_sub_property_name("", index, 0)?;
75 let members = privileges
76 .get_property_object(&name, 0)?
77 .get_num_sub_properties("")?;
78 println!(" {name:<12} {members} member(s)");
79 }
80
81 // The station itself, read-only.
82 println!("\nStation:");
83 match engine.current_user()? {
84 Some(current) => println!(" logged in as {}", current.login_name()?),
85 None => println!(" nobody logged in (usual when login is not required)"),
86 }
87 println!(
88 " is 'operator1' a real account here? {}",
89 engine.user_name_exists("operator1")?
90 );
91
92 // Where accounts actually live. Everything above this point exists only in
93 // memory: `new_user` builds a User, it does not enrol one. A user becomes
94 // part of the station when it is inserted into this file's list and the
95 // file is written.
96 let users_file = engine.users_file()?;
97 let file = users_file.as_property_object_file()?;
98 println!(
99 "
100Users file:"
101 );
102 println!(" path {}", file.path()?);
103 println!(
104 " users {}",
105 users_file.user_list()?.get_num_elements()?
106 );
107 println!(
108 " groups {}",
109 users_file.user_group_list()?.get_num_elements()?
110 );
111 println!(
112 " profiles {}",
113 users_file.user_profile_list()?.get_num_elements()?
114 );
115
116 // Deliberately not run: it would edit the station this example is reading.
117 // The two calls a host makes to enrol the user built above are
118 //
119 // users_file.user_list()?.set_num_elements(count + 1, 0)?; // then fill
120 // file.save_file_if_modified(false)?; // then write
121 //
122 // `false` matters: with `true` the engine puts a save dialog on screen, and
123 // a host with no operator would wait for an answer that never comes.
124 println!(
125 "
126 (this example does not write; enrolling a user would alter the station)"
127 );
128
129 Ok(())
130}