Skip to main content

User

Struct User 

Source
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

Source

pub fn login_name(&self) -> Result<String, Error>

The login name (User.LoginName).

§Errors

Error if the COM call fails or returns an unexpected type.

Examples found in repository?
examples/users_manage.rs (line 38)
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}
Source

pub fn set_login_name(&self, name: &str) -> Result<(), Error>

Sets the login name (User.LoginName).

§Errors

Error if the COM call fails.

Examples found in repository?
examples/users_manage.rs (line 34)
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}
Source

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?
examples/users_manage.rs (line 38)
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}
Source

pub fn set_full_name(&self, name: &str) -> Result<(), Error>

Sets the display name (User.FullName).

§Errors

Error if the COM call fails.

Examples found in repository?
examples/users_manage.rs (line 35)
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}
Source

pub fn set_password(&self, password: &str) -> Result<(), Error>

Sets the password (User.Password).

§Errors

Error if the COM call fails.

Examples found in repository?
examples/users_manage.rs (line 36)
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}
Source

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.

Source

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?
examples/users_manage.rs (line 43)
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}
Source

pub fn has_privilege(&self, privilege: UserPrivilege) -> Result<bool, Error>

Whether the user, or any group they belong to, holds a privilege (User.HasPrivilege).

§Errors

Error if the COM call fails or returns an unexpected type.

Examples found in repository?
examples/users_manage.rs (line 23)
17fn report_privileges(user: &User, privileges: &[UserPrivilege]) -> Result<(), rs_teststand::Error> {
18    for privilege in privileges {
19        // has_privilege answers for the user *and* any group they belong to.
20        println!(
21            "    {:<20} {}",
22            privilege.name(),
23            user.has_privilege(*privilege)?
24        );
25    }
26    Ok(())
27}
Source

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?
examples/users_manage.rs (line 66)
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}
Source

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?
examples/users_manage.rs (line 70)
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}
Source

pub fn members(&self) -> Result<PropertyObject, Error>

The member list of a user group (User.Members).

Only meaningful when this object represents a group rather than a person.

§Errors

Error if the COM call fails or returns an unexpected type.

Source

pub fn as_property_object(&self) -> Result<PropertyObject, Error>

The user as a plain property tree (User.AsPropertyObject).

§Errors

Error if the COM call fails or returns an unexpected type.

Trait Implementations§

Source§

impl Debug for User

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl !RefUnwindSafe for User

§

impl !Send for User

§

impl !Sync for User

§

impl !UnwindSafe for User

§

impl Freeze for User

§

impl Unpin for User

§

impl UnsafeUnpin for User

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.