include "modelling.alh" include "library.alh" include "primitives.alh" include "constructors.alh" include "object_operations.alh" include "mini_modify.alh" include "model_management.alh" include "ramify.alh" Element core = ? Void function main(): // Initialize the Core Formalism String core_location String core_model String admin_group String admin_user core_location = "models/CoreFormalism" // Create the Model itself and make public core = instantiate_model(import_node(core_location)) // Create admin group admin_group = instantiate_node(core, "Group", "") instantiate_attribute(core, admin_group, "name", "admin") // Create admin user admin_user = instantiate_node(core, "User", "") output("Desired username for admin user?") instantiate_attribute(core, admin_user, "name", input()) instantiate_attribute(core, admin_user, "admin", True) // Create link between admin user and group instantiate_link(core, "ownedBy", "", admin_group, admin_user) instantiate_link(core, "belongsTo", "", admin_user, admin_group) // Add the core formalism already core_model = instantiate_node(core, "Model", "") instantiate_attribute(core, core_model, "name", "CoreFormalism") instantiate_attribute(core, core_model, "location", core_location) instantiate_attribute(core, core_model, "permissions", "220") // Make necessary links for the formalism to the owners instantiate_link(core, "group", "", core_model, admin_group) instantiate_link(core, "owner", "", core_model, admin_user) // Switch all new users to the user_function // This accesses the bootstrap level, so do not change this unless you know what you are doing Element root root = read_root() dict_delete(root["__hierarchy"], "__IP") dict_add(root["__hierarchy"], "__IP", user_function) // Call this for ourselves as well user_function_skip_init(admin_user) // Done, so finish up // Admin user will have been deleted by the user_function as usual // Note that if there are no admin users left, it will be very difficult to manage, as nobody will have admin permissions! return ! Integer function get_relation_to_model(user_id : String, model_id : String): if (set_in(allAssociationDestinations(core, model_id, "owner"), user_id)): // We are the owner return 0! else: String group_id group_id = set_pop(allAssociationDestinations(core, model_id, "group")) if (set_in(allAssociationDestinations(core, user_id, "belongsTo"), group_id)): // We are in the owning group return 1! else: // We are not related whatsoever return 2! Boolean function is_admin(user_id : String): if (read_attribute(core, user_id, "admin")): return True! else: return False! Boolean function allow_read(user_id : String, model_id : String): if (is_admin(user_id)): // Is admin, so always allow return True! else: // Check permissions String permission permission = string_get(read_attribute(core, model_id, "permissions"), get_relation_to_model(user_id, model_id)) if (bool_or(permission == "1", permission == "2")): return True! else: return False! Boolean function allow_write(user_id : String, model_id : String): if (is_admin(user_id)): // Is admin, so always allow return True! else: // Check permissions String permission permission = string_get(read_attribute(core, model_id, "permissions"), get_relation_to_model(user_id, model_id)) if (permission == "2"): return True! else: return False! Boolean function allow_change_metadata(user_id : String, model_id : String): if (is_admin(user_id)): // Is admin, so always allow return True! else: if (get_relation_to_model(user_id, model_id) == 0): // Only owner can chmod return True! else: return False! Boolean function allow_group_modify(user_id : String, group_id : String): if (is_admin(user_id)): // Is admin, so always allow return True! else: if (read_nr_out(set_overlap(allIncomingAssociationInstances(core, user_id, "owner"), allOutgoingAssociationInstances(core, group_id, "owner"))) > 0): // We are an owner return True! else: return False! Boolean function check_login(user_id : String): // TODO return False! Element function user_function(): String username String user_id output("Log on as which user?") output("non-existing user will be created") username = input() user_id = get_user_id(username) if (user_id == ""): // New user // Add user to Core Formalism user_id = instantiate_node(core, "User", "") instantiate_attribute(core, user_id, "name", username) instantiate_attribute(core, user_id, "admin", False) // Now call with user created user_function_skip_init(user_id) else: if (check_login(user_id)): user_function_skip_init(user_id) // User destroyed already, so just stop execution return create_node()! String function get_model_id(name : String): Element models String model models = allInstances(core, "Model") while (read_nr_out(models) > 0): model = set_pop(models) if (value_eq(name, read_attribute(core, model, "name"))): return model! return ""! String function get_user_id(name : String): Element users String user users = allInstances(core, "User") while (read_nr_out(users) > 0): user = set_pop(users) if (value_eq(read_attribute(core, user, "name"), name)): return user! return ""! String function get_group_id(name : String): Element groups String group groups = allInstances(core, "Group") while (read_nr_out(groups) > 0): group = set_pop(groups) if (value_eq(read_attribute(core, group, "name"), name)): return group! return ""! Void function user_function_skip_init(user_id : String): Boolean do_continue String cmd do_continue = True output("Welcome to the Model Management Interface v2.0!") output("Use the 'help' command for a list of possible commands") while (do_continue): output("Ready for command...") cmd = input() if (cmd == "help"): output("Model operations") output(" model_add -- Add a new model") output(" model_modify -- Modify an existing model") output(" model_delete -- [TODO] Delete a model and all related transformations") output(" model_list -- List all models") output(" model_list_full -- List all models with full info") output("") output("Transformation-specific operations") output(" transformation_add_MT_language -- Create a RAMified metamodel") output(" transformation_reRAMify -- TODO") output(" transformation_add_MT -- TODO") output(" transformation_add_AL -- TODO") output(" transformation_source_add -- TODO") output(" transformation_source_delete -- TODO") output(" transformation_target_add -- TODO") output(" transformation_target_delete -- TODO") output(" transformation_execute -- TODO") output("") output("Model permission operations") output(" permission_modify -- Change model permissions") output(" permission_owner -- Change model owner") output(" permission_group -- Change model group") output("") output("Group operations") output(" group_create -- Create a group") output(" group_delete -- Delete a group") output(" group_owner_add -- Add group owner") output(" group_owner_delete -- Remove group owner") output(" group_join -- Add someone to your group") output(" group_kick -- Kick someone from your group") output(" group_list -- List all groups you are a member of") output("") output("Admin operations") output(" admin_promote -- Promote a user to admin status") output(" admin_demote -- Demote a user to normal status") output("") output("General operations") output(" account_delete -- Remove current user and revoke all permissions ") elif (cmd == "model_add"): // Model addition operation, which uses model upload commands of the compiler String name String type String location String type_id Element new_model String new_model_id output("Creating new model!") output("Model type?") type_id = get_model_id(input()) if (type_id != ""): // Type exists if (allow_read(user_id, type_id)): // And is readable output("Model name?") name = input() if (get_model_id(name) == ""): // Model doesn't exist yet output("Waiting for model constructors...") // TODO Update construct_model call to this interface // new_model = construct_model(read_attribute(core, type_id, "location")) output("Model upload success!") location = "/models/" + cast_id2s(new_model) export_node(new_model, location) // Manage meta-info new_model_id = instantiate_node(core, "Model", "") instantiate_attribute(core, new_model_id, "name", name) instantiate_attribute(core, new_model_id, "location", location) instantiate_attribute(core, new_model_id, "permissions", "200") instantiate_link(core, "owner", "", new_model_id, user_id) instantiate_link(core, "instanceOf", "", new_model_id, type_id) output("Meta-info correctly set!") else: output("Model with that name already exists!") else: output("You are not allowed to read this type model!") else: output("Could not find type model!") elif (cmd == "model_modify"): // Model modify operation, which uses the mini_modify.alc operations, though with extensions for access control String model_id String type_id output("Which model do you want to modify?") model_id = get_model_id(input()) if (model_id != ""): if (allow_read(user_id, model_id)): type_id = set_pop(allAssociationDestinations(core, model_id, "instanceOf")) if (allow_read(user_id, type_id)): modify(import_node(read_attribute(core, model_id, "location")), allow_write(user_id, model_id)) else: output("You are not allowed to read the type model!") else: output("You are not allowed to read this model!") else: output("Could not find model!") elif (cmd == "model_delete"): // Delete a model and all of its related transformations String model_id output("=================================================") output("WARNING: Deletion is a very destructive operation") output(" as it also deletes all transformations ") output(" defined which make use of this model! ") output("=================================================") output("") output("Currently not supported!") elif (cmd == "model_list"): // List all models Element models String m models = allInstances(core, "Model") while (read_nr_out(models) > 0): m = set_pop(models) output(string_join((string_join(" ", read_attribute(core, m, "name")) + " : "), read_attribute(core, set_pop(allAssociationDestinations(core, m, "instanceOf")), "name"))) elif (cmd == "model_list_full"): // List all models with full info Element models String m String permissions String owner String group String name String type String size models = allInstances(core, "Model") while (read_nr_out(models) > 0): m = set_pop(models) permissions = read_attribute(core, m, "permissions") owner = read_attribute(core, set_pop(allAssociationDestinations(core, m, "owner")), "name") group = read_attribute(core, set_pop(allAssociationDestinations(core, m, "group")), "name") name = read_attribute(core, m, "name") size = cast_i2s(read_nr_out(dict_read(import_node(read_attribute(core, m, "location")), "model"))) type = read_attribute(core, set_pop(allAssociationDestinations(core, m, "instanceOf")), "name") output(((((((((((" " + permissions) + " ") + owner) + " ") + group) + " ") + size) + " ") + name) + " : ") + type) elif (cmd == "transformation_add_MT_language"): // Create a model transformation language from a set of input and output formalisms String name String model_id Element source Element target Element all_formalisms Element merged_formalism Element ramified_formalism String old_type_id String type_id String location String new_model_id source = create_node() target = create_node() old_type_id = "" // Read source formalisms output("Source formalisms (terminate with empty string)?") name = input() while (name != ""): model_id = get_model_id(name) if (model_id != ""): if (allow_read(user_id, model_id)): type_id = set_pop(allAssociationDestinations(core, model_id, "instanceOf")) if (bool_or(old_type_id == "", type_id == old_type_id)): set_add(source, model_id) set_add(all_formalisms, create_tuple(name, import_node(read_attribute(core, model_id, "location")))) old_type_id = type_id elif (old_type_id != type_id): // Already have a previous type_id and now another: CLASH output("Cannot add model as types not compatible with previous models; try again") else: output("Model not readable; try again") name = input() else: output("No such model; try again") // Read target formalisms output("Target formalisms (terminate with empty string)?") name = input() while (name != ""): model_id = get_model_id(name) if (model_id != ""): if (allow_read(user_id, model_id)): type_id = set_pop(allAssociationDestinations(core, model_id, "instanceOf")) if (bool_or(old_type_id == "", type_id == old_type_id)): set_add(target, model_id) if (bool_not(set_in(source, model_id))): set_add(all_formalisms, create_tuple(name, import_node(read_attribute(core, model_id, "location")))) old_type_id = type_id elif (old_type_id != type_id): // Already have a previous type_id and now another: CLASH output("Cannot add model as types not compatible with previous models; try again") else: output("Model not readable; try again") name = input() else: output("No such model; try again") // Merge both into a single metamodel if (read_nr_out(source) > 0): if (read_nr_out(target) > 0): output("Name of the RAMified tranformation metamodel?") name = input() if (get_model_id(name) == ""): String merged_formalism_id String ramified_formalism_id String source_formalism_id String tracability_link // New location is available, so write merged_formalism = model_fuse(all_formalisms) location = "/models/" + cast_id2s(merged_formalism) export_node(merged_formalism, location) // Manage meta-info new_model_id = instantiate_node(core, "Model", "") merged_formalism_id = new_model_id instantiate_attribute(core, new_model_id, "name", "__merged_" + name) instantiate_attribute(core, new_model_id, "location", location) instantiate_attribute(core, new_model_id, "permissions", "200") instantiate_link(core, "owner", "", new_model_id, user_id) instantiate_link(core, "instanceOf", "", new_model_id, type_id) // Add tracability links at this level while (read_nr_out(all_formalisms) > 0): source_formalism_id = list_read(set_pop(all_formalisms), 1) tracability_link = instantiate_link(core, "tracability", "", merged_formalism_id, source_formalism_id) instantiate_attribute(core, tracability_link, "type", "merged") // Merge complete, now RAMify! ramified_formalism = ramify(merged_formalism) location = "/models/" + cast_id2s(ramified_formalism) export_node(ramified_formalism, location) // Manage meta-info new_model_id = instantiate_node(core, "Model", "") instantiate_attribute(core, new_model_id, "name", name) instantiate_attribute(core, new_model_id, "location", location) instantiate_attribute(core, new_model_id, "permissions", "200") instantiate_link(core, "owner", "", new_model_id, user_id) instantiate_link(core, "instanceOf", "", new_model_id, type_id) // Add tracability link at this level tracability_link = instantiate_link(core, "tracability", "", ramified_formalism_id, merged_formalism_id) instantiate_attribute(core, tracability_link, "type", "RAMified") else: output("Model already exists!") else: output("At least one target formalism is required") else: output("At least one source formalism is required") elif (cmd == "permission_modify"): String permissions Integer permission String model_id output("Which model do you want to change permissions of?") model_id = get_model_id(input()) if (model_id != ""): if (get_relation_to_model(user_id, model_id) == 0): output("New permissions?") permissions = input() Boolean fail Integer i i = 0 if (string_len(permissions) != 3): fail = True while (bool_and(bool_not(fail), i < 3)): permission = cast_s2i(string_get(permissions, i)) if (bool_or(permission < 0, permission > 2)): fail = True if (bool_not(fail)): unset_attribute(core, model_id, "permissions") instantiate_attribute(core, model_id, "permissions", permissions) else: output("Permissions must be a string of three characters with each character being a digit between 0 and 2") else: output("Permission denied!") else: output("No such model!") elif (cmd == "permission_owner"): String permissions String model_id String user_id output("Which model do you want to change owner of?") model_id = get_model_id(input()) if (model_id != ""): if (get_relation_to_model(user_id, model_id) == 0): output("New owner?") user_id = get_user_id(input()) if (user_id != ""): model_delete_element(core, set_pop(allOutgoingAssociationInstances(core, model_id, "owner"))) instantiate_link(core, "owner", "", model_id, user_id) else: output("No such user!") else: output("Permission denied!") else: output("No such model!") elif (cmd == "permission_group"): String permissions String model_id String group_id output("Which model do you want to change permissions of?") model_id = get_model_id(input()) if (model_id != ""): if (get_relation_to_model(user_id, model_id) == 0): output("New group?") group_id = get_group_id(input()) if (group_id != ""): model_delete_element(core, set_pop(allOutgoingAssociationInstances(core, model_id, "group"))) instantiate_link(core, "group", "", model_id, group_id) else: output("No such group!") else: output("Permission denied!") else: output("No such model!") elif (cmd == "group_create"): // Create a new group and become its owner String group_id String name output("Which group do you want to create?") name = input() group_id = get_group_id(name) if (group_id == ""): group_id = instantiate_node(core, "Group", "") instantiate_attribute(core, group_id, "name", name) instantiate_link(core, "belongsTo", "", user_id, group_id) instantiate_link(core, "owner", "", group_id, user_id) output("Group created!") else: output("Group already exists") elif (cmd == "group_delete"): // Delete an existing group String group_id String name output("Which group do you want to delete?") name = input() group_id = get_group_id(name) if (group_id != ""): if (allow_group_modify(user_id, group_id)): model_delete_element(core, group_id) else: output("Permission denied") else: output("No such group") elif (cmd == "group_owner_add"): // Add an owner to your group String group_id String other_user_id output("Which group do you want to add an owner to?") group_id = get_group_id(input()) if (group_id != ""): if (allow_group_modify(user_id, group_id)): output("Which user do you want to make an owner?") other_user_id = get_user_id(input()) if (other_user_id != ""): Element overlap overlap = set_overlap(allIncomingAssociationInstances(core, user_id, "owner"), allOutgoingAssociationInstances(core, group_id, "owner")) if (read_nr_out(overlap) == 0): instantiate_link(core, "owner", "", group_id, user_id) overlap = set_overlap(allOutgoingAssociationInstances(core, user_id, "belongsTo"), allIncomingAssociationInstances(core, group_id, "belongsTo")) if (read_nr_out(overlap) == 0): instantiate_link(core, "belongsTo", "", user_id, group_id) output("New owner added to group!") else: output("User is already an owner!") else: output("No such user") else: output("Permission denied!") else: output("No such group") elif (cmd == "group_owner_delete"): // Remove an owner from your group String group_id String other_user_id output("Which group do you want to disown someone from?") group_id = get_group_id(input()) if (group_id != ""): if (allow_group_modify(user_id, group_id)): output("Which user do you want to disown?") other_user_id = get_user_id(input()) if (other_user_id != ""): Element overlap overlap = set_overlap(allOutgoingAssociationInstances(core, user_id, "belongsTo"), allIncomingAssociationInstances(core, group_id, "belongsTo")) if (read_nr_out(overlap) > 0): overlap = set_overlap(allIncomingAssociationInstances(core, user_id, "owner"), allOutgoingAssociationInstances(core, group_id, "owner")) if (read_nr_out(overlap) > 0): model_delete_element(core, set_pop(overlap)) output("Disowned group from user!") else: output("User is not even an owner of the group!") else: output("User is not even a member of the group!") else: output("No such user") else: output("Permission denied!") else: output("No such group") elif (cmd == "group_join"): // Add someone to your group String group_id String other_user_id output("Which group do you want to add someone to?") group_id = get_group_id(input()) if (group_id != ""): if (allow_group_modify(user_id, group_id)): output("Which user do you want to add?") other_user_id = get_user_id(input()) if (other_user_id != ""): Element overlap overlap = set_overlap(allOutgoingAssociationInstances(core, user_id, "belongsTo"), allIncomingAssociationInstances(core, group_id, "belongsTo")) if (read_nr_out(overlap) == 0): instantiate_link(core, "belongsTo", "", user_id, group_id) output("User added to the group!") else: output("User is already a member of the group!") else: output("No such user") else: output("Permission denied!") else: output("No such group") elif (cmd == "group_kick"): // Remove someone from your group String group_id String other_user_id output("Which group do you want to kick someone from?") group_id = get_group_id(input()) if (group_id != ""): if (allow_group_modify(user_id, group_id)): output("Which user do you want to kick?") other_user_id = get_user_id(input()) if (other_user_id != ""): Element overlap overlap = set_overlap(allOutgoingAssociationInstances(core, user_id, "belongsTo"), allIncomingAssociationInstances(core, group_id, "belongsTo")) if (read_nr_out(overlap) > 0): model_delete_element(core, set_pop(overlap)) // Check if user was an owner as well overlap = set_overlap(allIncomingAssociationInstances(core, user_id, "owner"), allOutgoingAssociationInstances(core, group_id, "owner")) if (read_nr_out(overlap) > 0): model_delete_element(core, set_pop(overlap)) output("User kicked!") else: output("User is not even a member of the group!") else: output("No such user") else: output("Permission denied!") else: output("No such group") elif (cmd == "group_list"): // List all groups you are a member of (and whether you are admin or not!) Element groups String group_id String admin groups = allAssociationDestinations(core, user_id, "belongsTo") while (True): group_id = set_pop(groups) if (set_in(allOutgoingAssociationInstances(core, group_id, "owner"), user_id)): admin = " A " else: admin = " " output(string_join(admin, read_attribute(core, group_id, "name"))) elif (cmd == "admin_promote"): // Promote a user to admin status if (is_admin(user_id)): String other_user_id output("Which user do you want to promote?") other_user_id = get_user_id(input()) if (other_user_id != ""): unset_attribute(core, other_user_id, "admin") instantiate_attribute(core, other_user_id, "admin", True) output("Permissions granted!") else: output("No such user!") else: output("Permission denied!") elif (cmd == "admin_demote"): // Demote a user to normal status if (is_admin(user_id)): String other_user_id output("Which user do you want to demote?") other_user_id = get_user_id(input()) if (other_user_id != ""): unset_attribute(core, other_user_id, "admin") instantiate_attribute(core, other_user_id, "admin", False) output("Permissions revoked!") else: output("No such user!") else: output("Permission denied!") elif (cmd == "exit"): // Exit by actually removing the user and decoupling it from all of its models // Restarting with the same user name will NOT grant you access to anything of the previous user with that same name do_continue = False // Delete user from Core Formalism model_delete_element(core, user_id) output("Goodbye!") return !