░▒▓████████████████████████████████▓▒░ ░▒▓█ ▓▒░ ░▒▓█ ~ S W A M P ~ ▓▒░ ░▒▓█ ▓▒░ ░▒▓████████████████████████████████▓▒░
pplmvsvm
LOCATION:
/var/www/canvas/app/controllers/microsoft_sync
☗ ROOT
↻ REFRESH
✎ CARVE FLESH
EDITING: groups_controller.rb
# frozen_string_literal: true # # Copyright (C) 2021 - present Instructure, Inc. # # This file is part of Canvas. # # Canvas is free software: you can redistribute it and/or modify it under # the terms of the GNU Affero General Public License as published by the Free # Software Foundation, version 3 of the License. # # Canvas is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR # A PARTICULAR PURPOSE. See the GNU Affero General Public License for more # details. # # You should have received a copy of the GNU Affero General Public License along # with this program. If not, see <http://www.gnu.org/licenses/>. # @API Microsoft Sync - Groups # @internal # # API to manage MicrosoftSync::Groups. # # @model MicrosoftSync::Group # { # "id": "MicrosoftSync::Group", # "description": "The membership of a Microsoft group as well as the status of syncing Canvas enrollments to that group.", # "properties": { # "id": { # "description": "The id of the MicrosoftSync::Group", # "example": "4", # "type": "integer" # }, # "course_id": { # "description": "The id of the course related to the MicrosoftSync::Group", # "example": "8", # "type": "integer" # }, # "workflow_state": { # "description": "The current state of the MicrosoftSync::Group", # "example": "pending", # "type": "string", # "enum": [ # "pending", # "running", # "errored", # "completed" # ] # }, # "job_state": { # "description": "Internal data about the last step run for a job in the 'retrying' state. Only returned for site admins", # "type": "string" # }, # "last_synced_at": { # "description": "The time of the last successful sync", # "type": "datetime", # "example": "2012-07-20T15:00:00-06:00" # }, # "last_error": { # "description": "The last error encountered during an attempted sync", # "type": "string", # }, # "last_error_report_id": { # "description": "The ErrorReport ID for the last_error. Only returned for site admins", # "type": "integer", # }, # "root_account_id": { # "description": "The root account the MicrosoftSync::Group belongs to", # "type": "integer", # "example": "1" # }, # "created_at": { # "description": "The time the MicrosoftSync::Group was created", # "type": "datetime", # "example": "2012-07-20T15:00:00-06:00" # }, # "updated_at": { # "description": "The time the MicrosoftSync::Group was updated", # "type": "datetime", # "example": "2012-07-20T15:00:00-06:00" # } # } # } class MicrosoftSync::GroupsController < ApplicationController before_action :require_context before_action :require_user before_action :validate_user_permissions before_action :require_feature before_action :require_integration_available before_action :require_cooldown, only: :sync before_action :require_currently_not_syncing, only: :sync before_action :check_for_already_existing_group, only: :create before_action :check_for_enrollment_limits, only: :create # Create a new MicrosoftSync::Group for # the specified course. # # If a MicrosoftSync::Group already exists # for the course, this endpoints responds with # "409 conflict" # # @returns MicrosoftSync::Group def create # If a non-active group exists for the course, restore it. # Otherwise create a new group new_group = (already_existing_group&.restore! && already_existing_group) || MicrosoftSync::Group.create!(course:) render json: group_json(new_group), status: :created end # Get a single MicrosoftSync::Group # Returns the active MicrosoftSync::Group # associated with the specified course # # @returns MicrosoftSync::Group def show render json: group_json end # Destroy the MicrosoftSync::Group associated # with the specified course. # # These records are soft-deleted def destroy group.destroy! head :no_content end # Schedule a sync for the group associated # with the specified course. # # This action counts as a "manual sync" # # Manual syncs require a cooldown period # before another manual sync is allowed. def sync group.syncer_job.run_later group.update_unless_deleted(workflow_state: :manually_scheduled, last_manually_synced_at: Time.zone.now) render json: group_json end private def check_for_already_existing_group head :conflict if already_existing_group && !already_existing_group.deleted? end def check_for_enrollment_limits if MicrosoftSync::CanvasModelsHelpers.max_enrollment_owners_reached?(course) error_msg = t( "This course has too many teachers or other owner-type enrollments to " \ "be synced. Microsoft 365 allows a maximum of %{max_allowed} owners " \ "in a Team.", max_allowed: MicrosoftSync::MembershipDiff::MAX_ENROLLMENT_OWNERS ) elsif MicrosoftSync::CanvasModelsHelpers.max_enrollment_members_reached?(course) error_msg = t( "This course has too many enrolled users to be synced. Microsoft 365 " \ "allows a maximum of %{max_allowed} members in a Team.", max_allowed: MicrosoftSync::MembershipDiff::MAX_ENROLLMENT_MEMBERS ) end render json: { message: error_msg }, status: :unprocessable_entity if error_msg end # Don't allow scheduling a new job # if one is already running def require_currently_not_syncing return unless MicrosoftSync::Group::RUNNING_STATES.include?( group.workflow_state.to_sym ) render( json: { errors: ["A sync job is already running for the specified group"] }, status: :bad_request ) end # Prevents users from queueing a large number # of manual sync jobs by requiring a cooldown # period. # # Site admins can bypass this cooldown period. # # There are some states in which we allow scheduling # another manual sync right away. (errored, for example). # This method also allows scheduling the sync if the # group is in one of those states. def require_cooldown return if Account.site_admin.account_users_for(@current_user).present? return if MicrosoftSync::Group::COOLDOWN_NOT_REQUIRED_STATES.include?(group.workflow_state.to_sym) return if group.last_manually_synced_at.blank? return if Time.zone.now.to_i - group.last_manually_synced_at.to_i >= MicrosoftSync::Group.manual_sync_cooldown render json: { errors: ["Not enough time elapsed since last manual sync"] }, status: :bad_request end def require_feature return if course.root_account.feature_enabled?(:microsoft_group_enrollments_syncing) not_found end def require_integration_available return if course.root_account.settings[:microsoft_sync_enabled] render json: { errors: ["Integration not available"] }, status: :bad_request end def validate_user_permissions # Only users who can update course settings # should be permitted to manage the sync group render_unauthorized_action unless course.grants_right?( @current_user, session, :update ) end def course @context end # Group, whether deleted or not. def already_existing_group @already_existing_group ||= MicrosoftSync::Group.find_by(course:) end # The group, but only if not deleted. def group @group ||= MicrosoftSync::Group.not_deleted.find_by(course:) || (raise ActiveRecord::RecordNotFound) end def group_json(grp = nil) excludes = [:job_state] unless Account.site_admin.grants_right?(@current_user, :view_error_reports) excludes << :last_error_report_id end json = (grp || group).as_json(include_root: false, except: excludes) json[:last_error] = MicrosoftSync::Errors.deserialize_and_localize(json[:last_error]) json end end
CANCEL
Name
Type
Size
Modified
Actions
↩ ..
DIR
—
—
📄 groups_controller.rb
RB
8.1 KB
2023-09-24 03:39
EDIT