Ensure views only link to those actions allowed for current user
This commit is contained in:
@ -9,7 +9,6 @@ class CommentsController < ApplicationController
|
||||
end
|
||||
private :authorize!
|
||||
|
||||
# GET /comments
|
||||
# GET /comments.json
|
||||
def index
|
||||
file = CodeOcean::File.find(params[:file_id])
|
||||
@ -29,24 +28,11 @@ class CommentsController < ApplicationController
|
||||
authorize!
|
||||
end
|
||||
|
||||
# GET /comments/1
|
||||
# GET /comments/1.json
|
||||
def show
|
||||
authorize!
|
||||
end
|
||||
|
||||
# GET /comments/new
|
||||
def new
|
||||
@comment = Comment.new
|
||||
authorize!
|
||||
end
|
||||
|
||||
# GET /comments/1/edit
|
||||
def edit
|
||||
authorize!
|
||||
end
|
||||
|
||||
# POST /comments
|
||||
# POST /comments.json
|
||||
def create
|
||||
@comment = Comment.new(comment_params_without_request_id)
|
||||
@ -59,40 +45,31 @@ class CommentsController < ApplicationController
|
||||
send_mail_to_subscribers @comment, request_for_comment
|
||||
end
|
||||
|
||||
format.html { redirect_to @comment, notice: 'Comment was successfully created.' }
|
||||
format.json { render :show, status: :created, location: @comment }
|
||||
render :show, status: :created, location: @comment
|
||||
else
|
||||
format.html { render :new }
|
||||
format.json { render json: @comment.errors, status: :unprocessable_entity }
|
||||
render json: @comment.errors, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
authorize!
|
||||
end
|
||||
|
||||
# PATCH/PUT /comments/1
|
||||
# PATCH/PUT /comments/1.json
|
||||
def update
|
||||
respond_to do |format|
|
||||
if @comment.update(comment_params_without_request_id)
|
||||
format.html { head :no_content, notice: 'Comment was successfully updated.' }
|
||||
format.json { render :show, status: :ok, location: @comment }
|
||||
render :show, status: :ok, location: @comment
|
||||
else
|
||||
format.html { render :edit }
|
||||
format.json { render json: @comment.errors, status: :unprocessable_entity }
|
||||
render json: @comment.errors, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
authorize!
|
||||
end
|
||||
|
||||
# DELETE /comments/1
|
||||
# DELETE /comments/1.json
|
||||
def destroy
|
||||
authorize!
|
||||
@comment.destroy
|
||||
respond_to do |format|
|
||||
format.html { head :no_content, notice: 'Comment was successfully destroyed.' }
|
||||
format.json { head :no_content }
|
||||
end
|
||||
head :no_content
|
||||
end
|
||||
|
||||
private
|
||||
|
@ -39,6 +39,7 @@ class UserMailer < ActionMailer::Base
|
||||
end
|
||||
|
||||
def exercise_anomaly_detected(exercise_collection, anomalies)
|
||||
@user = exercise_collection.user
|
||||
@receiver_displayname = exercise_collection.user.displayname
|
||||
@collection = exercise_collection
|
||||
@anomalies = anomalies
|
||||
|
@ -8,7 +8,7 @@ class ExercisePolicy < AdminOrAuthorPolicy
|
||||
end
|
||||
|
||||
[:clone?, :destroy?, :edit?, :statistics?, :update?, :feedback?].each do |action|
|
||||
define_method(action) { admin? || author?}
|
||||
define_method(action) { admin? || author? }
|
||||
end
|
||||
|
||||
[:implement?, :working_times?, :intervention?, :search?, :submit?, :reload?].each do |action|
|
||||
|
@ -30,7 +30,7 @@ h2 Docker
|
||||
tbody
|
||||
- ExecutionEnvironment.order(:name).each do |execution_environment|
|
||||
tr data-id=execution_environment.id
|
||||
td.name = link_to(execution_environment, execution_environment)
|
||||
td.name = link_to_if(policy(execution_environment).show?, execution_environment, execution_environment)
|
||||
td.pool-size
|
||||
td.quantity = progress_bar(0)
|
||||
h3 = t('.history')
|
||||
|
@ -7,9 +7,9 @@
|
||||
- if object
|
||||
li.breadcrumb-item = object
|
||||
- else
|
||||
li.breadcrumb-item = link_to(model.model_name.human(count: 2), send(:"#{model.model_name.collection}_path"))
|
||||
li.breadcrumb-item = link_to_if(policy(model).show?, model.model_name.human(count: 2), send(:"#{model.model_name.collection}_path"))
|
||||
- if object
|
||||
li.breadcrumb-item = link_to(object, send(:"#{model.model_name.singular}_path", object))
|
||||
li.breadcrumb-item = link_to_if(policy(object).show?, object, send(:"#{model.model_name.singular}_path", object))
|
||||
li.breadcrumb-item.active
|
||||
- if I18n.translation_present?("shared.#{params[:action]}")
|
||||
= t("shared.#{params[:action]}")
|
||||
|
@ -6,8 +6,8 @@
|
||||
span.caret
|
||||
ul.dropdown-menu.p-0.mt-1 role='menu'
|
||||
- if current_user.admin?
|
||||
li = link_to(t('breadcrumbs.dashboard.show'), admin_dashboard_path, class: 'dropdown-item', 'data-turbolinks' => "false")
|
||||
li = link_to(t('breadcrumbs.statistics.show'), statistics_path, class: 'dropdown-item')
|
||||
li = link_to(t('breadcrumbs.dashboard.show'), admin_dashboard_path, class: 'dropdown-item', 'data-turbolinks' => "false") if policy([:admin, :dashboard]).show?
|
||||
li = link_to(t('breadcrumbs.statistics.show'), statistics_path, class: 'dropdown-item') if policy(:statistics).show?
|
||||
li.dropdown-divider role='separator'
|
||||
= render('navigation_submenu', title: t('activerecord.models.exercise.other'),
|
||||
models: [Exercise, ExerciseCollection, ProxyExercise, Tag, Submission], link: exercises_path, cached: true)
|
||||
|
@ -8,7 +8,7 @@
|
||||
- if current_user.try(:admin?) or current_user.try(:teacher?)
|
||||
li = link_to(t('consumers.show.link'), current_user.consumer, class: 'dropdown-item') if current_user.consumer and policy(current_user.consumer).show?
|
||||
li = link_to(t('internal_users.show.link'), current_user, class: 'dropdown-item') if policy(current_user).show?
|
||||
li = link_to(t('request_for_comments.index.all'), request_for_comments_path, class: 'dropdown-item') if policy(RequestForComment).index?
|
||||
li = link_to(t('request_for_comments.index.all'), request_for_comments_path, class: 'dropdown-item') if policy(:request_for_comment).index?
|
||||
li = link_to(t('request_for_comments.index.get_my_rfc_activity'), my_rfc_activity_path, class: 'dropdown-item')
|
||||
li = link_to(t('request_for_comments.index.get_my_comment_requests'), my_request_for_comments_path, class: 'dropdown-item')
|
||||
- if current_user.internal_user?
|
||||
|
@ -9,10 +9,10 @@ h1 = CodeHarborLink.model_name.human(count: 2)
|
||||
tbody
|
||||
- @code_harbor_links.each do |code_harbor_link|
|
||||
tr
|
||||
td = link_to(code_harbor_link.oauth2token, code_harbor_link)
|
||||
td = link_to(t('shared.show'), code_harbor_link)
|
||||
td = link_to(t('shared.edit'), edit_code_harbor_link_path(code_harbor_link))
|
||||
td = link_to(t('shared.destroy'), code_harbor_link, data: {confirm: t('shared.confirm_destroy')}, method: :delete)
|
||||
td = link_to_if(policy(code_harbor_link).show?, code_harbor_link.oauth2token, code_harbor_link)
|
||||
td = link_to(t('shared.show'), code_harbor_link) if policy(code_harbor_link).show?
|
||||
td = link_to(t('shared.edit'), edit_code_harbor_link_path(code_harbor_link)) if policy(code_harbor_link).edit?
|
||||
td = link_to(t('shared.destroy'), code_harbor_link, data: {confirm: t('shared.confirm_destroy')}, method: :delete) if policy(code_harbor_link).destroy?
|
||||
|
||||
= render('shared/pagination', collection: @code_harbor_links)
|
||||
p = render('shared/new_button', model: CodeHarborLink)
|
||||
|
@ -1,6 +1,6 @@
|
||||
h1
|
||||
= @code_harbor_link
|
||||
= render('shared/edit_button', object: @code_harbor_link) if policy(@code_harbor_link).edit?
|
||||
= render('shared/edit_button', object: @code_harbor_link)
|
||||
|
||||
- %w[oauth2token].each do |attribute|
|
||||
= row(label: "code_harbor_link.#{attribute}") do
|
||||
|
@ -1,33 +0,0 @@
|
||||
= form_for(@comment) do |f|
|
||||
- if @comment.errors.any?
|
||||
#error_explanation
|
||||
h2
|
||||
= pluralize(@comment.errors.count, "error")
|
||||
| prohibited this comment from being saved:
|
||||
|
||||
ul
|
||||
- @comment.errors.full_messages.each do |message|
|
||||
li= message
|
||||
|
||||
.field
|
||||
= f.label :user_id
|
||||
br/
|
||||
= f.text_field :user_id
|
||||
.field
|
||||
= f.label :file_id
|
||||
br/
|
||||
= f.text_field :file_id
|
||||
.field
|
||||
= f.label :row
|
||||
br/
|
||||
= f.number_field :row
|
||||
.field
|
||||
= f.label :column
|
||||
br/
|
||||
= f.number_field :column
|
||||
.field
|
||||
= f.label :text
|
||||
br/
|
||||
= f.text_field :text
|
||||
.actions
|
||||
= f.submit
|
@ -1,7 +0,0 @@
|
||||
h1 Editing comment
|
||||
|
||||
= render 'form'
|
||||
|
||||
= link_to 'Show', @comment
|
||||
| |
|
||||
= link_to 'Back', comments_path
|
@ -1,24 +0,0 @@
|
||||
h1 Listing comments
|
||||
|
||||
table
|
||||
thead
|
||||
tr
|
||||
th User
|
||||
th File
|
||||
th Row
|
||||
th Column
|
||||
th Text
|
||||
th colspan="3"
|
||||
tbody
|
||||
- @comments.each do |comment|
|
||||
tr
|
||||
td= comment.user
|
||||
td= comment.file
|
||||
td= comment.row
|
||||
td= comment.column
|
||||
td= comment.text
|
||||
td= link_to 'Show', comment
|
||||
td= link_to 'Edit', edit_comment_path(comment)
|
||||
td= link_to 'Destroy', comment, method: :delete, data: confirm: 'Are you sure?'
|
||||
br/
|
||||
= link_to 'New Comment', new_comment_path
|
@ -1,5 +0,0 @@
|
||||
h1 New comment
|
||||
|
||||
= render 'form'
|
||||
|
||||
= link_to 'Back', comments_path
|
@ -1,25 +0,0 @@
|
||||
p#notice= notice
|
||||
|
||||
p
|
||||
strong User:
|
||||
= @comment.user
|
||||
|
||||
p
|
||||
strong File:
|
||||
= @comment.file
|
||||
|
||||
p
|
||||
strong Row:
|
||||
= @comment.row
|
||||
|
||||
p
|
||||
strong Column:
|
||||
= @comment.column
|
||||
|
||||
p
|
||||
strong Text:
|
||||
= @comment.text
|
||||
|
||||
= link_to 'Edit', edit_comment_path(@comment)
|
||||
| |
|
||||
= link_to 'Back', comments_path
|
@ -9,10 +9,10 @@ h1 = Consumer.model_name.human(count: 2)
|
||||
tbody
|
||||
- @consumers.each do |consumer|
|
||||
tr
|
||||
td = link_to(consumer.name, consumer)
|
||||
td = link_to(t('shared.show'), consumer)
|
||||
td = link_to(t('shared.edit'), edit_consumer_path(consumer))
|
||||
td = link_to(t('shared.destroy'), consumer, data: {confirm: t('shared.confirm_destroy')}, method: :delete)
|
||||
td = link_to_if(policy(consumer).show?, consumer.name, consumer)
|
||||
td = link_to(t('shared.show'), consumer) if policy(consumer).show?
|
||||
td = link_to(t('shared.edit'), edit_consumer_path(consumer)) if policy(consumer).edit?
|
||||
td = link_to(t('shared.destroy'), consumer, data: {confirm: t('shared.confirm_destroy')}, method: :delete) if policy(consumer).destroy?
|
||||
|
||||
= render('shared/pagination', collection: @consumers)
|
||||
p = render('shared/new_button', model: Consumer)
|
||||
|
@ -1,6 +1,6 @@
|
||||
h1
|
||||
= @consumer
|
||||
= render('shared/edit_button', object: @consumer) if policy(@consumer).edit?
|
||||
= render('shared/edit_button', object: @consumer)
|
||||
|
||||
= row(label: 'consumer.name', value: @consumer.name)
|
||||
- %w[oauth_key oauth_secret].each do |attribute|
|
||||
|
@ -8,7 +8,7 @@ h1 = ErrorTemplateAttribute.model_name.human(count: 2)
|
||||
th = t('activerecord.attributes.error_template_attribute.key')
|
||||
th = t('activerecord.attributes.error_template_attribute.description')
|
||||
th = t('activerecord.attributes.error_template_attribute.regex')
|
||||
th colspan=5 = t('shared.actions')
|
||||
th colspan=3 = t('shared.actions')
|
||||
tbody
|
||||
- @error_template_attributes.each do |error_template_attribute|
|
||||
tr
|
||||
@ -17,13 +17,13 @@ h1 = ErrorTemplateAttribute.model_name.human(count: 2)
|
||||
span class="fa fa-star" aria-hidden="true"
|
||||
- else
|
||||
span class="fa fa-star-o" aria-hidden="true"
|
||||
td = link_to(error_template_attribute.key, error_template_attribute)
|
||||
td = link_to_if(policy(error_template_attribute).show?, error_template_attribute.key, error_template_attribute)
|
||||
td = error_template_attribute.description
|
||||
td
|
||||
code = error_template_attribute.regex
|
||||
td = link_to(t('shared.show'), error_template_attribute)
|
||||
td = link_to(t('shared.edit'), edit_error_template_attribute_path(error_template_attribute))
|
||||
td = link_to(t('shared.destroy'), error_template_attribute, data: {confirm: t('shared.confirm_destroy')}, method: :delete)
|
||||
td = link_to(t('shared.show'), error_template_attribute) if policy(error_template_attribute).show?
|
||||
td = link_to(t('shared.edit'), edit_error_template_attribute_path(error_template_attribute)) if policy(error_template_attribute).edit?
|
||||
td = link_to(t('shared.destroy'), error_template_attribute, data: {confirm: t('shared.confirm_destroy')}, method: :delete) if policy(error_template_attribute).destroy?
|
||||
|
||||
= render('shared/pagination', collection: @error_template_attributes)
|
||||
p = render('shared/new_button', model: ErrorTemplateAttribute)
|
||||
|
@ -11,12 +11,12 @@ h1 = ErrorTemplate.model_name.human(count: 2)
|
||||
tbody
|
||||
- @error_templates.each do |error_template|
|
||||
tr
|
||||
td = link_to(error_template.name, error_template)
|
||||
td = link_to_if(policy(error_template).show?, error_template.name, error_template)
|
||||
td = error_template.description
|
||||
td = link_to(error_template.execution_environment)
|
||||
td = link_to(t('shared.show'), error_template)
|
||||
td = link_to(t('shared.edit'), edit_error_template_path(error_template))
|
||||
td = link_to(t('shared.destroy'), error_template, data: {confirm: t('shared.confirm_destroy')}, method: :delete)
|
||||
td = link_to(t('shared.show'), error_template) if policy(error_template).show?
|
||||
td = link_to(t('shared.edit'), edit_error_template_path(error_template)) if policy(error_template).edit?
|
||||
td = link_to(t('shared.destroy'), error_template, data: {confirm: t('shared.confirm_destroy')}, method: :delete) if policy(error_template).destroy?
|
||||
|
||||
= render('shared/pagination', collection: @error_templates)
|
||||
p = render('shared/new_button', model: ErrorTemplate)
|
||||
|
@ -3,7 +3,7 @@ h1
|
||||
= render('shared/edit_button', object: @error_template)
|
||||
|
||||
= row(label: 'error_template.name', value: @error_template.name)
|
||||
= row(label: 'exercise.execution_environment', value: link_to(@error_template.execution_environment))
|
||||
= row(label: 'exercise.execution_environment', value: link_to_if(policy(@error_template.execution_environment).show?, @error_template.execution_environment))
|
||||
= row(label: "error_template.signature") do
|
||||
code = @error_template.signature
|
||||
- [:description, :hint].each do |attribute|
|
||||
@ -29,12 +29,13 @@ h2.mt-4
|
||||
span class="fa fa-star" aria-hidden="true"
|
||||
- else
|
||||
span class="fa fa-star-o" aria-hidden="true"
|
||||
td = link_to(attribute.key, attribute)
|
||||
td = link_to_if(policy(attribute).show?, attribute.key, attribute)
|
||||
td = attribute.description
|
||||
td
|
||||
code = attribute.regex
|
||||
td = link_to(t('shared.show'), attribute)
|
||||
td = link_to(t('shared.destroy'), attribute_error_template_url(:error_template_attribute_id => attribute.id), :method => :delete)
|
||||
td = link_to(t('shared.show'), attribute) if policy(attribute).show?
|
||||
td = link_to(t('shared.edit'), edit_error_template_attribute_path(attribute)) if policy(attribute).edit?
|
||||
td = link_to(t('shared.destroy'), attribute_error_template_url(:error_template_attribute_id => attribute.id), :method => :delete) if policy(attribute).destroy?
|
||||
|
||||
#add-attribute
|
||||
= collection_select({}, :error_template_attribute_id,
|
||||
|
@ -3,7 +3,7 @@ h1
|
||||
= render('shared/edit_button', object: @execution_environment)
|
||||
|
||||
= row(label: 'execution_environment.name', value: @execution_environment.name)
|
||||
= row(label: 'execution_environment.user', value: link_to(@execution_environment.author, @execution_environment.author))
|
||||
= row(label: 'execution_environment.user', value: link_to_if(policy(@execution_environment.author).show?, @execution_environment.author, @execution_environment.author))
|
||||
= row(label: 'execution_environment.file_type', value: @execution_environment.file_type.present? ? link_to(@execution_environment.file_type, @execution_environment.file_type) : nil)
|
||||
- [:docker_image, :exposed_ports, :memory_limit, :network_enabled, :permitted_execution_time, :pool_size].each do |attribute|
|
||||
= row(label: "execution_environment.#{attribute}", value: @execution_environment.send(attribute))
|
||||
|
@ -14,7 +14,7 @@ h1 = @execution_environment
|
||||
- if wts then average_time = wts["average_time"] else 0
|
||||
- if wts then stddev_time = wts["stddev_time"] else 0
|
||||
tr
|
||||
td = link_to exercise.title, controller: "exercises", action: "statistics", id: exercise.id, 'data-turbolinks' => "false"
|
||||
td = link_to_if policy(exercise).show?, exercise.title, controller: "exercises", action: "statistics", id: exercise.id, 'data-turbolinks' => "false"
|
||||
td = us["users"]
|
||||
td = us["average_score"].to_f.round(4)
|
||||
td = us["maximum_score"].to_f.round(2)
|
||||
|
@ -13,13 +13,13 @@ h1 = ExerciseCollection.model_name.human(count: 2)
|
||||
- @exercise_collections.each do |collection|
|
||||
tr
|
||||
td = collection.id
|
||||
td = link_to(collection.name, collection)
|
||||
td = link_to_if(policy(collection).show?, collection.name, collection)
|
||||
td = collection.updated_at
|
||||
td = collection.exercises.size
|
||||
td = link_to(t('shared.show'), collection)
|
||||
td = link_to(t('shared.edit'), edit_exercise_collection_path(collection))
|
||||
td = link_to(t('shared.statistics'), statistics_exercise_collection_path(collection))
|
||||
td = link_to(t('shared.destroy'), collection, data: {confirm: t('shared.confirm_destroy')}, method: :delete)
|
||||
td = link_to(t('shared.show'), collection) if policy(collection).show?
|
||||
td = link_to(t('shared.edit'), edit_exercise_collection_path(collection)) if policy(collection).edit?
|
||||
td = link_to(t('shared.statistics'), statistics_exercise_collection_path(collection)) if policy(collection).statistics?
|
||||
td = link_to(t('shared.destroy'), collection, data: {confirm: t('shared.confirm_destroy')}, method: :delete) if policy(collection).destroy?
|
||||
|
||||
= render('shared/pagination', collection: @exercise_collections)
|
||||
p = render('shared/new_button', model: ExerciseCollection)
|
||||
|
@ -3,7 +3,7 @@ h1
|
||||
= render('shared/edit_button', object: @exercise_collection)
|
||||
|
||||
= row(label: 'exercise_collections.name', value: @exercise_collection.name)
|
||||
= row(label: 'exercise_collections.user', value: link_to(@exercise_collection.user.name, @exercise_collection.user)) unless @exercise_collection.user.nil?
|
||||
= row(label: 'exercise_collections.user', value: link_to_if(policy(@exercise_collection.user).show?, @exercise_collection.user.name, @exercise_collection.user)) unless @exercise_collection.user.nil?
|
||||
= row(label: 'exercise_collections.use_anomaly_detection', value: @exercise_collection.use_anomaly_detection)
|
||||
= row(label: 'exercise_collections.updated_at', value: @exercise_collection.updated_at)
|
||||
|
||||
@ -22,7 +22,7 @@ h4.mt-4 = t('activerecord.attributes.exercise_collections.exercises')
|
||||
- exercise = exercise_collection_item.exercise
|
||||
tr
|
||||
td = exercise_collection_item.position
|
||||
td = link_to(exercise.title, exercise)
|
||||
td = link_to_if(policy(exercise).show?, exercise.title, exercise)
|
||||
td = link_to_if(exercise.execution_environment && policy(exercise.execution_environment).show?, exercise.execution_environment, exercise.execution_environment)
|
||||
td = link_to_if(exercise.user && policy(exercise.user).show?, exercise.user.name, exercise.user)
|
||||
td = link_to(t('shared.statistics'), statistics_exercise_path(exercise), 'data-turbolinks' => "false")
|
||||
td = link_to(t('shared.statistics'), statistics_exercise_path(exercise), 'data-turbolinks' => "false") if policy(exercise).statistics?
|
||||
|
@ -1,4 +1,4 @@
|
||||
h1 = link_to(@exercise, exercise_path(@exercise))
|
||||
h1 = link_to_if(policy(@exercise).show?, @exercise, exercise_path(@exercise))
|
||||
|
||||
.feedback-page
|
||||
.header = t('activerecord.attributes.exercise.description')
|
||||
|
@ -27,7 +27,7 @@ h1 = Exercise.model_name.human(count: 2)
|
||||
tbody
|
||||
- @exercises.each do |exercise|
|
||||
tr data-id=exercise.id
|
||||
td.p-1.pt-2 = link_to(exercise.title, exercise, 'data-turbolinks' => "false") if policy(exercise).show?
|
||||
td.p-1.pt-2 = link_to_if(policy(exercise).show?, exercise.title, exercise, 'data-turbolinks' => "false")
|
||||
td.p-1.pt-2 = link_to_if(exercise.execution_environment && policy(exercise.execution_environment).show?, exercise.execution_environment, exercise.execution_environment)
|
||||
td.p-1.pt-2 = exercise.files.teacher_defined_tests.count
|
||||
td.p-1.pt-2 = exercise.maximum_score
|
||||
|
@ -7,8 +7,7 @@
|
||||
|
||||
h1
|
||||
= @exercise
|
||||
- if policy(@exercise).edit?
|
||||
= render('shared/edit_button', object: @exercise)
|
||||
= render('shared/edit_button', object: @exercise)
|
||||
|
||||
= row(label: 'exercise.title', value: @exercise.title)
|
||||
= row(label: 'exercise.user', value: link_to_if(policy(@exercise.author).show?, @exercise.author, @exercise.author))
|
||||
|
@ -49,7 +49,7 @@ h1 = @exercise
|
||||
- if user_statistics[user.id] then us = user_statistics[user.id] else us = {"maximum_score" => nil, "runs" => nil}
|
||||
- label = "#{user.displayname}"
|
||||
tr
|
||||
td = link_to_if symbol==:external_users, label, {controller: "exercises", action: "statistics", external_user_id: user.id, id: @exercise.id}
|
||||
td = link_to_if symbol==:external_users && policy(user).statistics?, label, {controller: "exercises", action: "statistics", external_user_id: user.id, id: @exercise.id}
|
||||
td = us['maximum_score'] or 0
|
||||
td = us['runs']
|
||||
td = @exercise.average_working_time_for(user.id) or 0
|
||||
|
@ -10,8 +10,8 @@ h1 = ExternalUser.model_name.human(count: 2)
|
||||
tbody
|
||||
- @users.each do |user|
|
||||
tr
|
||||
td = user.name
|
||||
td = link_to(user.consumer, user.consumer)
|
||||
td = link_to(t('shared.show'), user)
|
||||
td = link_to_if(policy(user).show?, user.name)
|
||||
td = link_to_if(policy(user.consumer).show?, user.consumer, user.consumer)
|
||||
td = link_to(t('shared.show'), user) if policy(user).show?
|
||||
|
||||
= render('shared/pagination', collection: @users)
|
||||
|
@ -5,7 +5,7 @@ h1 = @user.name
|
||||
= row(label: 'external_user.consumer', value: link_to(@user.consumer, @user.consumer))
|
||||
= row(label: 'external_user.role', value: t("users.roles.#{@user.role}"))
|
||||
|
||||
h4.mt-4 = link_to(t('.exercise_statistics'), statistics_external_user_path(@user))
|
||||
h4.mt-4 = link_to(t('.exercise_statistics'), statistics_external_user_path(@user)) if policy(@user).statistics?
|
||||
|
||||
h4.mt-4 = t('.tag_statistics')
|
||||
#loading
|
||||
|
@ -13,7 +13,7 @@ h1 = t('.title')
|
||||
- if statistics[exercise.id]
|
||||
- stats = statistics[exercise.id]
|
||||
tr
|
||||
td = link_to exercise, controller: "exercises", action: "statistics", external_user_id: @user.id, id: exercise.id
|
||||
td = link_to_if policy(exercise).show?, exercise, controller: "exercises", action: "statistics", external_user_id: @user.id, id: exercise.id
|
||||
td = stats["maximum_score"] or 0
|
||||
td = stats["runs"] or 0
|
||||
td = stats["working_time"] or 0
|
||||
|
@ -10,11 +10,11 @@ h1 = FileTemplate.model_name.human(count: 2)
|
||||
tbody
|
||||
- @file_templates.each do |file_template|
|
||||
tr
|
||||
td = link_to(file_template.name, file_template)
|
||||
td = link_to(file_template.file_type, file_type_path(file_template.file_type))
|
||||
td = link_to(t('shared.show'), file_template)
|
||||
td = link_to(t('shared.edit'), edit_file_template_path(file_template))
|
||||
td = link_to(t('shared.destroy'), file_template, data: {confirm: t('shared.confirm_destroy')}, method: :delete)
|
||||
td = link_to_if(policy(file_template).show?, file_template.name, file_template)
|
||||
td = link_to_if(policy(file_template.file_type).show?, file_template.file_type, file_type_path(file_template.file_type))
|
||||
td = link_to(t('shared.show'), file_template) if policy(file_template).show?
|
||||
td = link_to(t('shared.edit'), edit_file_template_path(file_template)) if policy(file_template).edit?
|
||||
td = link_to(t('shared.destroy'), file_template, data: {confirm: t('shared.confirm_destroy')}, method: :delete) if policy(file_template).destroy?
|
||||
|
||||
= render('shared/pagination', collection: @file_templates)
|
||||
p = render('shared/new_button', model: FileTemplate)
|
||||
|
@ -3,5 +3,5 @@ h1
|
||||
= render('shared/edit_button', object: @file_template)
|
||||
|
||||
= row(label: 'file_template.name', value: @file_template.name)
|
||||
= row(label: 'file_template.file_type', value: link_to(@file_template.file_type, file_type_path(@file_template.file_type)))
|
||||
= row(label: 'file_template.file_type', value: link_to_if(policy(@file_template.file_type).show?, @file_template.file_type, file_type_path(@file_template.file_type)))
|
||||
= row(label: 'file_template.content', value: @file_template.content)
|
||||
|
@ -3,6 +3,6 @@ h1
|
||||
= render('shared/edit_button', object: @file_type)
|
||||
|
||||
= row(label: 'file_type.name', value: @file_type.name)
|
||||
= row(label: 'file_type.user', value: link_to(@file_type.author, @file_type.author))
|
||||
= row(label: 'file_type.user', value: link_to_if(policy(@file_type.author).show?, @file_type.author, @file_type.author))
|
||||
- [:editor_mode, :file_extension, :indent_size, :binary, :executable, :renderable].each do |attribute|
|
||||
= row(label: "file_type.#{attribute}", value: @file_type.send(attribute))
|
||||
|
@ -22,14 +22,12 @@ h1 = InternalUser.model_name.human(count: 2)
|
||||
tbody
|
||||
- @users.each do |user|
|
||||
tr
|
||||
td = user.name
|
||||
td = user.consumer ? link_to(user.consumer, user.consumer) : empty
|
||||
td = link_to_if(policy(user).show?, user.name)
|
||||
td = user.consumer ? link_to_if(policy(user.consumer).show?, user.consumer, user.consumer) : empty
|
||||
td = t("users.roles.#{user.role}")
|
||||
td = link_to(t('shared.show'), user)
|
||||
td = link_to(t('shared.edit'), edit_internal_user_path(user))
|
||||
td
|
||||
- if policy(user).destroy?
|
||||
= link_to(t('shared.destroy'), user, data: {confirm: t('shared.confirm_destroy')}, method: :delete)
|
||||
td = link_to(t('shared.show'), user) if policy(user).show?
|
||||
td = link_to(t('shared.edit'), edit_internal_user_path(user)) if policy(user).edit?
|
||||
td = link_to(t('shared.destroy'), user, data: {confirm: t('shared.confirm_destroy')}, method: :delete) if policy(user).destroy?
|
||||
|
||||
= render('shared/pagination', collection: @users)
|
||||
p = render('shared/new_button', model: InternalUser)
|
||||
|
@ -1,10 +1,9 @@
|
||||
h1
|
||||
= @user
|
||||
- if policy(@user).edit?
|
||||
= render('shared/edit_button', object: @user)
|
||||
= render('shared/edit_button', object: @user)
|
||||
|
||||
= row(label: 'internal_user.email', value: @user.email)
|
||||
= row(label: 'internal_user.name', value: @user.name)
|
||||
= row(label: 'internal_user.consumer', value: @user.consumer ? link_to(@user.consumer, @user.consumer) : nil)
|
||||
= row(label: 'internal_user.consumer', value: @user.consumer ? link_to_if(policy(@user.consumer).show?, @user.consumer, @user.consumer) : nil)
|
||||
= row(label: 'internal_user.role', value: t("users.roles.#{@user.role}"))
|
||||
= row(label: 'internal_user.activated', value: @user.activated?)
|
||||
|
@ -5,10 +5,11 @@ h1 = Intervention.model_name.human(count: 2)
|
||||
thead
|
||||
tr
|
||||
th = t('activerecord.attributes.intervention.name')
|
||||
th = t('shared.actions')
|
||||
tbody
|
||||
- @interventions.each do |intervention|
|
||||
tr
|
||||
td = intervention.name
|
||||
td = link_to(t('shared.show'), intervention)
|
||||
td = link_to_if policy(intervention).show?, intervention.name
|
||||
td = link_to(t('shared.show'), intervention) if policy(intervention).show?
|
||||
|
||||
= render('shared/pagination', collection: @interventions)
|
||||
|
@ -18,7 +18,7 @@
|
||||
= collection_check_boxes :proxy_exercise, :exercise_ids, @exercises, :id, :title do |b|
|
||||
tr
|
||||
td = b.check_box
|
||||
td = link_to(b.object, b.object)
|
||||
td = link_to_if(policy(b.object).show?, b.object, b.object)
|
||||
td = l(b.object.created_at, format: :short)
|
||||
|
||||
.actions = render('shared/submit_button', f: f, object: @proxy_exercise)
|
@ -12,11 +12,11 @@ h1 = ProxyExercise.model_name.human(count: 2)
|
||||
th.p-1 = sort_link(@search, :title, t('activerecord.attributes.proxy_exercise.title'))
|
||||
th.p-1 = t('activerecord.attributes.exercise.token')
|
||||
th.p-1 = t('activerecord.attributes.proxy_exercise.files_count')
|
||||
th.p-1 colspan=6 = t('shared.actions')
|
||||
th.p-1 colspan=2 = t('shared.actions')
|
||||
tbody
|
||||
- @proxy_exercises.each do |proxy_exercise|
|
||||
tr data-id=proxy_exercise.id
|
||||
td.p-1.pt-2 = link_to(proxy_exercise.title,proxy_exercise)
|
||||
td.p-1.pt-2 = link_to_if(policy(proxy_exercise).show?, proxy_exercise.title, proxy_exercise)
|
||||
td.p-1.pt-2 = proxy_exercise.token
|
||||
td.p-1.pt-2 = proxy_exercise.count_files
|
||||
td.p-1.pt-2 = link_to(t('shared.edit'), edit_proxy_exercise_path(proxy_exercise)) if policy(proxy_exercise).edit?
|
||||
|
@ -7,8 +7,7 @@
|
||||
|
||||
h1
|
||||
= @proxy_exercise.title
|
||||
- if policy(@proxy_exercise).edit?
|
||||
= render('shared/edit_button', object: @proxy_exercise)
|
||||
= render('shared/edit_button', object: @proxy_exercise)
|
||||
|
||||
= row(label: 'exercise.title', value: @proxy_exercise.title)
|
||||
= row(label: 'proxy_exercise.files_count', value: @exercises.count)
|
||||
@ -24,5 +23,5 @@ h2.mt-4 Exercises
|
||||
th = sort_link(@search, :created_at, t('shared.created_at'))
|
||||
- @proxy_exercise.exercises.each do |exercise|
|
||||
tr
|
||||
td = link_to(exercise.title, exercise)
|
||||
td = link_to_if(policy(exercise).show?, exercise.title, exercise)
|
||||
td = l(exercise.created_at, format: :short)
|
||||
|
@ -1,8 +1,8 @@
|
||||
hr
|
||||
h5.mt-4 Admin Menu
|
||||
ul.text
|
||||
li = link_to "User's current status of this exercise", statistics_external_user_exercise_path(id: @request_for_comment.exercise_id, external_user_id: @request_for_comment.user_id)
|
||||
li = link_to "All exercises of this user", statistics_external_user_path(id: @request_for_comment.user_id)
|
||||
li = link_to "User's current status of this exercise", statistics_external_user_exercise_path(id: @request_for_comment.exercise_id, external_user_id: @request_for_comment.user_id) if policy(@request_for_comment.exercise).statistics?
|
||||
li = link_to "All exercises of this user", statistics_external_user_path(id: @request_for_comment.user_id) if policy(@request_for_comment.user).statistics?
|
||||
ul.text
|
||||
li = link_to "Implement the exercise yourself", implement_exercise_path(id: @request_for_comment.exercise_id)
|
||||
li = link_to "Show the exercise", exercise_path(id: @request_for_comment.exercise_id)
|
||||
li = link_to "Implement the exercise yourself", implement_exercise_path(id: @request_for_comment.exercise_id) if policy(@request_for_comment.exercise).implement?
|
||||
li = link_to "Show the exercise", exercise_path(id: @request_for_comment.exercise_id) if policy(@request_for_comment.exercise).show?
|
||||
|
@ -1,28 +0,0 @@
|
||||
= form_for(@request_for_comment) do |f|
|
||||
- if @request_for_comment.errors.any?
|
||||
#error_explanation
|
||||
h2
|
||||
= pluralize(@request_for_comment.errors.count, "error")
|
||||
| prohibited this request_for_comment from being saved:
|
||||
ul
|
||||
- @request_for_comment.errors.full_messages.each do |message|
|
||||
li= message
|
||||
|
||||
.field
|
||||
= f.label :user_id
|
||||
br/
|
||||
= f.number_field :user_id
|
||||
.field
|
||||
= f.label :exercise_id
|
||||
br/
|
||||
= f.number_field :exercise_id
|
||||
.field
|
||||
= f.label :file_id
|
||||
br/
|
||||
= f.number_field :file_id
|
||||
.field
|
||||
= f.label :user_type
|
||||
br/
|
||||
= f.text_field :user_type
|
||||
.actions
|
||||
= f.submit
|
@ -32,8 +32,8 @@ h1 = RequestForComment.model_name.human(count: 2)
|
||||
span class="fa fa-check" style="color:darkgrey" aria-hidden="true"
|
||||
- else
|
||||
td = ''
|
||||
td = link_to(request_for_comment.exercise.title, request_for_comment)
|
||||
- if request_for_comment.has_attribute?(:question) && request_for_comment.question
|
||||
td = link_to_if(policy(request_for_comment.exercise).show?, request_for_comment.exercise.title, request_for_comment)
|
||||
- if request_for_comment.has_attribute?(:question) && request_for_comment.question.present?
|
||||
td = truncate(request_for_comment.question, length: 200)
|
||||
- else
|
||||
td = '-'
|
||||
|
@ -2,12 +2,12 @@
|
||||
h4#exercise_caption.list-group-item-heading data-comment-exercise-url=create_comment_exercise_request_for_comment_path data-exercise-id="#{@request_for_comment.exercise.id}" data-rfc-id="#{@request_for_comment.id}"
|
||||
- if @request_for_comment.solved?
|
||||
span.fa.fa-check aria-hidden="true"
|
||||
= link_to(@request_for_comment.exercise.title, [:implement, @request_for_comment.exercise])
|
||||
= link_to_if(policy(@request_for_comment.exercise).show?, @request_for_comment.exercise.title, [:implement, @request_for_comment.exercise])
|
||||
p.list-group-item-text
|
||||
- user = @request_for_comment.user
|
||||
- submission = @request_for_comment.submission
|
||||
- testruns = Testrun.where(:submission_id => @request_for_comment.submission)
|
||||
= user.displayname
|
||||
= link_to_if(policy(user).show?, user.displayname, user)
|
||||
| | #{@request_for_comment.created_at.localtime}
|
||||
.rfc
|
||||
.description
|
||||
@ -22,7 +22,7 @@
|
||||
= t('activerecord.attributes.request_for_comments.question')
|
||||
.text
|
||||
- question = @request_for_comment.question
|
||||
= question.nil? or question.empty? ? t('request_for_comments.no_question') : question
|
||||
= question.blank? ? t('request_for_comments.no_question') : question
|
||||
|
||||
- if policy(@request_for_comment).mark_as_solved? and not @request_for_comment.solved?
|
||||
= render('mark_as_solved')
|
||||
|
@ -1,3 +1,4 @@
|
||||
// default value for fetch will always be evaluated even if it is not returned
|
||||
- link_target = local_assigns.fetch(:path, false) || send(:"edit_#{object.class.name.underscore}_path", object)
|
||||
= link_to(t('shared.edit'), link_target, class: 'btn btn-secondary float-right')
|
||||
- if policy(object).edit?
|
||||
// default value for fetch will always be evaluated even if it is not returned
|
||||
- link_target = local_assigns.fetch(:path, false) || send(:"edit_#{object.class.name.underscore}_path", object)
|
||||
= link_to(t('shared.edit'), link_target, class: 'btn btn-secondary float-right')
|
||||
|
@ -7,4 +7,4 @@
|
||||
- if file.teacher_defined_test?
|
||||
= row(label: 'file.feedback_message', value: render_markdown(file.feedback_message), class: 'm-0')
|
||||
= row(label: 'file.weight', value: file.weight)
|
||||
= row(label: 'file.content', value: file.native_file? ? link_to(file.native_file.file.filename, file.native_file.url) : code_tag(file.content))
|
||||
= row(label: 'file.content', value: file.native_file? ? link_to_if(policy(file.native_file.file.filename).show?, file.native_file.file.filename, file.native_file.url) : code_tag(file.content))
|
||||
|
@ -21,12 +21,12 @@ h1 = Submission.model_name.human(count: 2)
|
||||
tbody
|
||||
- @submissions.each do |submission|
|
||||
tr
|
||||
td = link_to(submission.exercise, submission.exercise)
|
||||
td = link_to(submission.user, submission.user)
|
||||
td = link_to_if(policy(submission.exercise).show?, submission.exercise, submission.exercise)
|
||||
td = link_to_if(policy(submission.user).show?, submission.user, submission.user)
|
||||
td = t("submissions.causes.#{submission.cause}")
|
||||
td = submission.score
|
||||
td = l(submission.created_at, format: :short)
|
||||
td = link_to(t('shared.show'), submission)
|
||||
td = link_to(t('shared.statistics'), statistics_submission_path(submission))
|
||||
td = link_to(t('shared.show'), submission) if policy(submission).show?
|
||||
td = link_to(t('shared.statistics'), statistics_submission_path(submission)) if policy(submission).statistics?
|
||||
|
||||
= render('shared/pagination', collection: @submissions)
|
||||
|
@ -7,8 +7,8 @@
|
||||
|
||||
h1 = @submission
|
||||
|
||||
= row(label: 'submission.exercise', value: link_to(@submission.exercise, @submission.exercise))
|
||||
= row(label: 'submission.user', value: link_to(@submission.user, @submission.user))
|
||||
= row(label: 'submission.exercise', value: link_to_if(policy(@submission.exercise).show?, @submission.exercise, @submission.exercise))
|
||||
= row(label: 'submission.user', value: link_to_if(policy(@submission.user).show?, @submission.user, @submission.user))
|
||||
= row(label: 'submission.cause', value: t("submissions.causes.#{@submission.cause}"))
|
||||
= row(label: 'submission.score', value: @submission.score)
|
||||
|
||||
|
@ -23,4 +23,4 @@ h2.mt-4 = t('.history')
|
||||
td = l(submission.created_at, format: :short)
|
||||
td = submission.score
|
||||
td = progress_bar(submission.percentage)
|
||||
td = link_to(t('shared.show'), submission)
|
||||
td = link_to(t('shared.show'), submission) if policy(submission).show?
|
||||
|
@ -9,10 +9,10 @@ h1 = Tag.model_name.human(count: 2)
|
||||
tbody
|
||||
- @tags.each do |tag|
|
||||
tr
|
||||
td = tag.name
|
||||
td = link_to(t('shared.show'), tag)
|
||||
td = link_to(t('shared.edit'), edit_tag_path(tag))
|
||||
td = link_to(t('shared.destroy'), tag, data: {confirm: t('shared.confirm_destroy')}, method: :delete) if tag.can_be_destroyed?
|
||||
td = link_to_if(policy(tag).show?, tag.name, tag)
|
||||
td = link_to(t('shared.show'), tag) if policy(tag).show?
|
||||
td = link_to(t('shared.edit'), edit_tag_path(tag)) if policy(tag).edit?
|
||||
td = link_to(t('shared.destroy'), tag, data: {confirm: t('shared.confirm_destroy')}, method: :delete) if tag.can_be_destroyed? && policy(tag).destroy?
|
||||
|
||||
= render('shared/pagination', collection: @tags)
|
||||
p = render('shared/new_button', model: Tag, path: new_tag_path)
|
||||
|
@ -12,16 +12,15 @@ h1 = UserExerciseFeedback.model_name.human(count: 2)
|
||||
table.table
|
||||
thead
|
||||
tr
|
||||
th colspan=2 = t('activerecord.attributes.user_exercise_feedback.user')
|
||||
th = t('activerecord.attributes.user_exercise_feedback.user')
|
||||
th = t('activerecord.attributes.user_exercise_feedback.exercise')
|
||||
th colspan=2 = t('shared.actions')
|
||||
tbody
|
||||
- @uefs.each do |uef|
|
||||
tr
|
||||
td = uef.user.id
|
||||
td = uef.user.name
|
||||
td = link_to(uef.exercise.title, uef.exercise)
|
||||
td = link_to(t('shared.show'), uef)
|
||||
td = link_to(t('shared.destroy'), uef, data: {confirm: t('shared.confirm_destroy')}, method: :delete)
|
||||
td = link_to_if(policy(uef.user).show?, uef.user.name)
|
||||
td = link_to_if(policy(uef.exercise).show?, uef.exercise.title, uef.exercise)
|
||||
td = link_to(t('shared.show'), uef) if policy(uef).show?
|
||||
td = link_to(t('shared.destroy'), uef, data: {confirm: t('shared.confirm_destroy')}, method: :delete) if policy(uef).destroy?
|
||||
|
||||
= render('shared/pagination', collection: @uefs)
|
||||
|
@ -1,7 +1,7 @@
|
||||
h2 = @uef
|
||||
|
||||
= row(label: 'activerecord.attributes.user_exercise_feedback.exercise', value: link_to(@uef.exercise.title, @uef.exercise))
|
||||
= row(label: 'user_exercise_feedback.user', value: @uef.user)
|
||||
= row(label: 'activerecord.attributes.user_exercise_feedback.exercise', value: link_to_if(policy(@uef.exercise).show?, @uef.exercise.title, @uef.exercise))
|
||||
= row(label: 'user_exercise_feedback.user', value: link_to_if(policy(@uef.user).show?, @uef.user))
|
||||
= row(label: 'activerecord.attributes.user_exercise_feedback.feedback_text', value: @uef.feedback_text)
|
||||
= row(label: 'user_exercise_feedback.difficulty', value: @uef.difficulty)
|
||||
= row(label: 'user_exercise_feedback.working_time', value: @uef.user_estimated_worktime)
|
||||
|
@ -12,9 +12,9 @@ table(border=1)
|
||||
- @anomalies.keys.each do | id |
|
||||
- exercise = Exercise.find(id)
|
||||
tr
|
||||
td = link_to(exercise.title, exercise_path(exercise))
|
||||
td = link_to_if(policy(@user, exercise).show?, exercise.title, exercise_path(exercise))
|
||||
td = @anomalies[id]
|
||||
td = link_to(t('shared.statistics', locale: :de), statistics_exercise_path(exercise))
|
||||
td = link_to_if(policy(@user, exercise).statistics?, t('shared.statistics', locale: :de), statistics_exercise_path(exercise))
|
||||
|
||||
|
||||
== t('mailers.user_mailer.exercise_anomaly_detected.body2',
|
||||
@ -31,8 +31,8 @@ table(border=1)
|
||||
- @anomalies.keys.each do | id |
|
||||
- exercise = Exercise.find(id)
|
||||
tr
|
||||
td = link_to(exercise.title, exercise_path(exercise))
|
||||
td = link_to_if(policy(@user, exercise).show?, exercise.title, exercise_path(exercise))
|
||||
td = @anomalies[id]
|
||||
td = link_to(t('shared.statistics', locale: :en), statistics_exercise_path(exercise))
|
||||
td = link_to_if(policy(@user, exercise).statistics?, t('shared.statistics', locale: :en), statistics_exercise_path(exercise))
|
||||
|
||||
== t('mailers.user_mailer.exercise_anomaly_detected.body3')
|
||||
|
@ -1 +1,7 @@
|
||||
== t('mailers.user_mailer.got_new_comment.body', receiver_displayname: @receiver_displayname, link_to_comment: link_to(@rfc_link, @rfc_link), commenting_user_displayname: @commenting_user_displayname, comment_text: @comment_text, link_my_comments: link_to(t('request_for_comments.index.get_my_comment_requests'), my_request_for_comments_url), link_all_comments: link_to(t('request_for_comments.index.all'), request_for_comments_url) )
|
||||
== t('mailers.user_mailer.got_new_comment.body',
|
||||
receiver_displayname: @receiver_displayname,
|
||||
link_to_comment: link_to(@rfc_link, @rfc_link),
|
||||
commenting_user_displayname: @commenting_user_displayname,
|
||||
comment_text: @comment_text,
|
||||
link_my_comments: link_to(t('request_for_comments.index.get_my_comment_requests'), my_request_for_comments_url),
|
||||
link_all_comments: link_to(t('request_for_comments.index.all'), request_for_comments_url) )
|
||||
|
@ -1 +1,5 @@
|
||||
== t('mailers.user_mailer.send_thank_you_note.body', receiver_displayname: @receiver_displayname, link_to_comment: link_to(@rfc_link, @rfc_link), author: @author, thank_you_note: @thank_you_note )
|
||||
== t('mailers.user_mailer.send_thank_you_note.body',
|
||||
receiver_displayname: @receiver_displayname,
|
||||
link_to_comment: link_to(@rfc_link, @rfc_link),
|
||||
author: @author,
|
||||
thank_you_note: @thank_you_note )
|
||||
|
@ -21,7 +21,7 @@ Rails.application.routes.draw do
|
||||
post :set_thank_you_note
|
||||
end
|
||||
end
|
||||
resources :comments
|
||||
resources :comments, defaults: { format: :json }
|
||||
get '/my_request_for_comments', as: 'my_request_for_comments', to: 'request_for_comments#get_my_comment_requests'
|
||||
get '/my_rfc_activity', as: 'my_rfc_activity', to: 'request_for_comments#get_rfcs_with_my_comments'
|
||||
|
||||
|
@ -169,6 +169,7 @@ ActiveRecord::Schema.define(version: 2018_11_29_093207) do
|
||||
t.string "name", limit: 255
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.string "role", default: "learner", null: false
|
||||
end
|
||||
|
||||
create_table "file_templates", force: :cascade do |t|
|
||||
|
Reference in New Issue
Block a user