修改默认程序
对于本教程,您将使用具有分配和检索角色功能的程序替换模板源代码文件。
修改默认程序:
1.在文本编辑器中打开src/access_hello/main.mo文件,然后删除现有内容。
2.将以下示例代码复制并粘贴到文件中:
// Import base modules
import AssocList "mo:base/AssocList";
import Error "mo:base/Error";
import List "mo:base/List";
shared({ caller = initializer }) actor class() {
// Establish role-based greetings to display
public shared({ caller }) func greet(name : Text) : async Text {
if (has_permission(caller, #assign_role)) {
return "Hello, " # name # ". You have a role with administrative privileges."
} else if (has_permission(caller, #lowest)) {
return "Welcome, " # name # ". You have an authorized account. Would you like to play a game?";
} else {
return "Greetings, " # name # ". Nice to meet you!";
}
};
// Define custom types
public type Role = {
#owner;
#admin;
#authorized;
};
public type Permission = {
#assign_role;
#lowest;
};
private stable var roles: AssocList.AssocList<Principal, Role> = List.nil();
private stable var role_requests: AssocList.AssocList<Principal, Role> = List.nil();
func principal_eq(a: Principal, b: Principal): Bool {
return a == b;
};
func get_role(pal: Principal) : ?Role {
if (pal == initializer) {
?#owner;
} else {
AssocList.find<Principal, Role>(roles, pal, principal_eq);
}
};
// Determine if a principal has a role with permissions
func has_permission(pal: Principal, perm : Permission) : Bool {
let role = get_role(pal);
switch (role, perm) {
case (?#owner or ?#admin, _) true;
case (?#authorized, #lowest) true;
case (_, _) false;
}
};
// Reject unauthorized user identities
func require_permission(pal: Principal, perm: Permission) : async () {
if ( has_permission(pal, perm) == false ) {
throw Error.reject( "unauthorized" );
}
};
// Assign a new role to a principal
public shared({ caller }) func assign_role( assignee: Principal, new_role: ?Role ) : async () {
await require_permission( caller, #assign_role );
switch new_role {
case (?#owner) {
throw Error.reject( "Cannot assign anyone to be the owner" );
};
case (_) {};
};
if (assignee == initializer) {
throw Error.reject( "Cannot assign a role to the canister owner" );
};
roles := AssocList.replace<Principal, Role>(roles, assignee, principal_eq, new_role).0;
role_requests := AssocList.replace<Principal, Role>(role_requests, assignee, principal_eq, null).0;
};
public shared({ caller }) func request_role( role: Role ) : async Principal {
role_requests := AssocList.replace<Principal, Role>(role_requests, caller, principal_eq, ?role).0;
return caller;
};
// Return the principal of the message caller/user identity
public shared({ caller }) func callerPrincipal() : async Principal {
return caller;
};
// Return the role of the message caller/user identity
public shared({ caller }) func my_role() : async ?Role {
return get_role(caller);
};
public shared({ caller }) func my_role_request() : async ?Role {
AssocList.find<Principal, Role>(role_requests, caller, principal_eq);
};
public shared({ caller }) func get_role_requests() : async List.List<(Principal,Role)> {
await require_permission( caller, #assign_role );
return role_requests;
};
public shared({ caller }) func get_roles() : async List.List<(Principal,Role)> {
await require_permission( caller, #assign_role );
return roles;
};
};
让我们看一下该程序的一些关键要素:
您可能会注意到greet函数是您在先前教程中看到的greet函数的变体。但是,在此程序中,greet函数使用消息调用方来确定应用的权限,并基于与调用方相关联的权限来确定要显示的问候。
该程序定义了两种自定义类型-一种用于Role,一种用于Permissions。
Assign_roles函数使消息调用者可以将角色分配给与身份关联的主体。
使用callerPrincipal函数,您可以返回与身份关联的主体。
使用my_role函数可以返回与身份关联的角色。
3.保存并关闭main.mo文件。
最后更新于