Changes between Version 9 and Version 10 of AdvancedApplicationDevelopment


Ignore:
Timestamp:
09/24/25 23:26:36 (3 weeks ago)
Author:
226026
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • AdvancedApplicationDevelopment

    v9 v10  
    99* Контрола на пристап во рамки на проект
    1010
    11 == Погледи
    12 === Поглед за прикажување на сите одговори на даден топик
    13 {{{
    14 create or replace view v_discussion_thread
    15 as
    16 with recursive
    17     depth_table as
    18         (select parent_id, id, 0 as depth
    19          from discussion_thread
    20          UNION ALL
    21          select discuss.parent_id, dpth.id, dpth.depth + 1
    22          from depth_table dpth
    23                   join discussion_thread discuss
    24                        on dpth.parent_id = discuss.id),
    25     tmp as (select id, max(depth) as depth
    26             from depth_table
    27             group by id)
    28 select d.id as id, t.user_id as user_id, d.depth as depth, d1.parent_id as parent_id, t.created_at as "created_at"
    29 from tmp d
    30          join depth_table d1
    31               on d.id = d1.id and d1.depth = d.depth
    32          join thread t
    33               on t.id = d.id;
    34 }}}
     11== Напреден апликативен развој
    3512
    36 === Поглед за прикажување на пермисиите за дадена улога во за сите канали во даден проект.
    37 {{{
    38 CREATE OR REPLACE VIEW role_channel_permissions AS
    39 SELECT
    40     c.project_resource_id,
    41     c.name,
    42     pr.id as role_id,
    43     COALESCE(
    44                     STRING_AGG(
    45                     DISTINCT rp.permission_name, ',' ORDER BY rp.permission_name
    46                               ) FILTER (
    47                         WHERE
    48                         (pr.override_type = 'INCLUDE' AND rpo.project_resource_id IS NOT NULL)
    49                             OR
    50                         (pr.override_type = 'EXCLUDE' AND rpo.project_resource_id IS NULL)
    51                         ),
    52                     ''
    53     ) AS permissions
    54 FROM channel c
    55          JOIN project_role pr
    56               ON pr.project_id = c.project_id
    57          LEFT JOIN role_permissions rp
    58                    ON rp.role_id = pr.id
    59                        AND rp.permission_name IN ('READ','WRITE')
    60          LEFT JOIN role_permissions_overrides rpo
    61                    ON rpo.role_id = pr.id
    62                        AND rpo.permission_name = rp.permission_name
    63                        AND rpo.project_resource_id = c.project_resource_id
    64 GROUP BY c.project_resource_id, c.name,pr.id
    65 }}}
    66 
    67 == Транзакции
    68 === Прифаќање на пријава и зачувување на приложениот feedback
    69 {{{
    70 @Transactional
    71     public void accept(BBUser creator, Integer reqId) {
    72         ProjectRequests prReq = getRequestById(reqId);
    73         prReq.setStatus(Status.ACCEPTED);
    74 
    75         feedbackService.create(creator,FeedbackFor.P,prReq);
    76         projectService.addDeveloperToProject(prReq.getProject(), prReq.getCreator());
    77         prReqRepo.save(prReq);
    78     }
    79 }}}
    80 
    81 === Одбивање на пријава и зачувување на прилоѓениот feedback
    82 {{{
    83 @Transactional
    84     public void deny(Integer reqId, String desc, BBUser creator) {
    85         ProjectRequests prReq = getRequestById(reqId);
    86         prReq.setStatus(Status.DENIED);
    87         feedbackService.create(desc,creator,FeedbackFor.P,prReq);
    88         prReqRepo.save(prReq);
    89     }
    90 }}}
    91 
    92 === Ажурирање на постоечка улога
    93 {{{
    94 @Transactional
    95     public void updateRole(Integer id, AddRoleDTOEntities addRoleDTO) {
    96 
    97         ProjectRole existingRole = projectRoleRepository.findById(id).orElseThrow(() -> new IllegalArgumentException("bad role id"));
    98         projectRolePermissionRepository.deleteAllByIdRole(existingRole);
    99 
    100         existingRole.setName(addRoleDTO.getName());
    101         existingRole.setOverrideType(addRoleDTO.getProjectResourcePermissionOverrideType().toString());
    102 
    103         projectRoleRepository.save(existingRole);
    104 
    105         List<ProjectRolePermission> newGlobalPermissions = mapGlobalsToProjectRolePermissions(existingRole, addRoleDTO.getGlobalPermissions());
    106         List<ProjectRolePermission> newPerResourcePermissions = mapPerResourceToProjectRolePermissions(existingRole,addRoleDTO.getPermissionsResourceWrappers());
    107         List<ProjectRolePermissionResourceOverride> resourceOverrides = mapToResourceOverrides(getResources(addRoleDTO.getPermissionsResourceWrappers()),newPerResourcePermissions);
    108 
    109 
    110         projectRolePermissionRepository.saveAll(newGlobalPermissions);
    111         projectRolePermissionRepository.saveAll(newPerResourcePermissions);
    112         projectRolePermissionResourceOverrideRepository.saveAll(resourceOverrides);
    113 
    114     }
    115 
    116 }}}
    117 === Додавање на нова улога во проект
    118 {{{
    119     @Transactional
    120     public void addRole(AddRoleDTOEntities addRoleDTO) {
    121         ProjectRole role = projectRoleRepository.save(
    122                 new ProjectRole(
    123                         addRoleDTO.getProject(),
    124                         addRoleDTO.getName(),
    125                         addRoleDTO.getProjectResourcePermissionOverrideType().toString()
    126                 )
    127         );
    128 
    129         List<ProjectRolePermission> entities = mapPerResourceToProjectRolePermissions(role, addRoleDTO.getPermissionsResourceWrappers());
    130         projectRolePermissionRepository.saveAll(mapGlobalsToProjectRolePermissions(role, addRoleDTO.getGlobalPermissions()));
    131         projectRolePermissionRepository.saveAll(entities);
    132         projectRolePermissionResourceOverrideRepository.saveAll(mapToResourceOverrides(
    133                 getResources(addRoleDTO.getPermissionsResourceWrappers()),
    134                 entities
    135         ));
    136 }}}
    137 {{{}}}
    138 
    139 
    140 
    141 
    142 
    143 
    144 
    145 == Тригери
    146 === Проверка дали даден топик имат уникатно име во парент threadот
    147 {{{
    148 CREATE OR REPLACE FUNCTION fn_validate_topic_title()
    149     RETURNS TRIGGER
    150     LANGUAGE plpgsql
    151 AS
    152 $$
    153 BEGIN
    154     IF new.title IN
    155        (SELECT title
    156         FROM topic_thread
    157                  AS t
    158         WHERE t.parent_id = new.parent_id
    159            OR (t.parent_id IS NULL AND new.parent_id IS NULL)
    160        )
    161     THEN
    162         RAISE EXCEPTION 'There already exists a topic with title % in parent topic with id %',new.title,new.parent_id;
    163     END IF;
    164     RETURN new;
    165 END;
    166 $$;
    167 }}}
    168 {{{
    169 CREATE OR REPLACE TRIGGER tr_check_topic_name --RADI
    170     BEFORE INSERT OR UPDATE
    171     ON topic_thread
    172     FOR EACH ROW
    173 EXECUTE FUNCTION fn_validate_topic_title();
    174 }}}
    175 
    176 === При креирање на топик, креаторот се внесува како модератор
    177 {{{
    178 CREATE OR REPLACE FUNCTION fn_insert_topics_creator_as_moderator()
    179     RETURNS TRIGGER
    180     LANGUAGE plpgsql
    181 AS
    182 $$
    183 DECLARE
    184     v_user_id INT;
    185 BEGIN
    186     SELECT v_topic_thread.user_id
    187     INTO v_user_id
    188     FROM v_topic_thread
    189     WHERE v_topic_thread.id = new.id;
    190     IF not check_if_user_exists_in('moderator', 'id', v_user_id::text) THEN
    191         INSERT INTO moderator values (v_user_id);
    192     END IF;
    193     INSERT INTO topic_threads_moderators(thread_id, user_id) VALUES (new.id, v_user_id);
    194     RETURN NEW;
    195 END
    196 $$;
    197 }}}
    198 {{{
    199 CREATE OR REPLACE TRIGGER tr_insert_topics_creator_as_moderator
    200     AFTER INSERT
    201     ON topic_thread
    202     FOR EACH ROW
    203 EXECUTE FUNCTION fn_insert_topics_creator_as_moderator();
    204 }}}
    205 
    206 === При бришење на topic, проверка дали модераторот сеуште модерира topicци
    207 {{{
    208 CREATE OR REPLACE FUNCTION fn_remove_orphan_moderator()
    209     RETURNS trigger
    210     LANGUAGE plpgsql
    211 AS $function$
    212 BEGIN
    213     IF not exists (
    214         select 1
    215         from topic_threads_moderators t
    216         where t.user_id = OLD.user_id
    217     )
    218     THEN
    219         DELETE FROM moderator where id=OLD.user_id;
    220     END IF;
    221     IF not exists (
    222         select 1
    223         from topic_threads_moderators t
    224         where t.thread_id = OLD.thread_id
    225     )
    226     THEN
    227         delete from discussion_thread where parent_id=OLD.thread_id;
    228         DELETE FROM topic_thread where id = OLD.thread_id;
    229 --      delete from thread where id =  OLD.thread_id;
    230     END IF;
    231     RETURN OLD;
    232 END;
    233 }}}
    234 
    235 {{{
    236 CREATE OR REPLACE TRIGGER tr_remove_orphan_moderator
    237     AFTER DELETE
    238     ON topic_threads_moderators
    239     FOR EACH ROW
    240 EXECUTE FUNCTION fn_remove_orphan_moderator();
    241 }}}
    242 
    243 === При креирање на проект, креаторот се внесува како PROJECT_OWNER
    244 {{{
    245 CREATE OR REPLACE FUNCTION fn_insert_project_manager()
    246     RETURNS TRIGGER
    247     LANGUAGE plpgsql
    248 AS
    249 $$
    250 DECLARE
    251     usrId      INT;
    252     new_project_id INT;
    253 BEGIN
    254     SELECT user_id, id
    255     into usrId,new_project_id
    256     FROM v_project_thread p
    257     WHERE NEW.id = p.id;
    258     IF not EXISTS(
    259         select 1
    260         from developer_associated_with_project dawp
    261         where dawp.project_id=new_project_id and dawp.developer_id=usrId
    262     ) THEN
    263         INSERT INTO developer_associated_with_project(project_id, developer_id, started_at)
    264         values (new_project_id, usrId, NOW());
    265     end if;
    266     IF not check_if_user_exists_in('project_manager', 'id', usrId::text) THEN
    267         INSERT INTO project_manager VALUES (usrId);
    268     end if;
    269     RETURN NEW;
    270 END
    271 $$;
    272 }}}
    273 
    274 {{{
    275 CREATE OR REPLACE TRIGGER tr_a_insert_project_manager --RADI
    276     AFTER INSERT
    277     ON project_thread
    278     FOR EACH ROW
    279 EXECUTE FUNCTION fn_insert_project_manager();
    280 }}}
    281 
    282 
    283 === Бришење на не користени тагови
    284 
    285 {{{
    286 create or replace function fn_delete_dangling_tags()
    287     RETURNS trigger
    288     LANGUAGE plpgsql
    289 AS $$
    290 BEGIN
    291     IF NOT EXISTS(select 1
    292                   from tag_threads
    293                   where tag_name = OLD.tag_name
    294                   group by tag_name) THEN
    295         delete from tag where name = OLD.tag_name;
    296     end if;
    297     RETURN OLD;
    298 END;
    299 $$;
    300 }}}
    301 
    302 {{{
    303 create or replace trigger tr_delete_dangling_tags
    304     after delete
    305     on tag_threads
    306     for each row
    307     execute function fn_delete_dangling_tags();
    308 }}}
    309 
    310 === Внесување на даден корисник како developer, откако ќе стани дел од даден проект
    311 {{{
    312 create or replace function fn_add_dev_if_not_exist()
    313     returns trigger
    314     language plpgsql
    315 as $$
    316 BEGIN
    317     IF NOT check_if_user_exists_in('developer','id',new.developer_id::text) THEN
    318         INSERT INTO developer values (NEW.developer_id);
    319     end if;
    320     RETURN new;
    321 end;
    322 $$;
    323 
    324 }}}
    325 
    326 {{{
    327 create or replace trigger tr_add_dev_if_not_exist
    328     before insert on developer_associated_with_project
    329     for each row
    330 execute function fn_add_dev_if_not_exist();
    331 }}}
    332 
    333 === Креирање на General канал, при креирање на даден проект
    334 {{{
    335 create or replace function fn_insert_general_for_project()
    336     returns trigger
    337     language plpgsql
    338 as $$
    339 DECLARE
    340     developer_id INT;
    341     project_resource_id INT;
    342 BEGIN
    343     select user_id
    344     into developer_id
    345     from thread t
    346     where t.id=NEW.id;
    347     insert into project_resource default values returning id into project_resource_id;
    348 
    349     insert into channel(name,description,project_id,developer_id,project_resource_id)
    350     values ('General','General',NEW.id,developer_id,project_resource_id);
    351 
    352     return new;
    353 end;
    354 $$;
    355 }}}
    356 
    357 {{{
    358 create or replace trigger tr_insert_general_for_project
    359     after insert on project_thread
    360     for each row
    361 execute function fn_insert_general_for_project();
    362 }}}
    363 
    364 === Сите 'pending' пријави за даден корисник стануваат 'accepted', при додавање на тој корисник во 'blacklist' листата.
    365 {{{
    366 CREATE OR REPLACE FUNCTION fn_change_status_on_pending_reports()
    367     RETURNS TRIGGER
    368     LANGUAGE plpgsql
    369 AS $$
    370 BEGIN
    371     RAISE NOTICE 'user_id: %, topic_id: %', NEW.user_id, NEW.topic_id;
    372 
    373 UPDATE submission
    374 SET status = 'ACCEPTED'
    375 WHERE id in (
    376     select id
    377     from report r
    378     where r.for_user_id = NEW.user_id and r.thread_id = NEW.topic_id
    379 );
    380 
    381 RETURN NEW;
    382 END;
    383 $$;
    384 }}}
    385 
    386 {{{
    387 CREATE OR REPLACE TRIGGER tr_change_status_on_pending_reports
    388     AFTER INSERT
    389     ON blacklisted_user
    390     FOR EACH ROW
    391 EXECUTE FUNCTION fn_change_status_on_pending_reports();
    392 }}}
    393 
    394 === Оневозможувено повторно додавање на корисник во 'blacklist' листата, доколку е веќе присутен на неа
    395 
    396 {{{
    397 create or replace function fn_add_blacklisted_user()
    398 RETURNS trigger
    399 LANGUAGE plpgsql
    400 AS $$
    401 BEGIN
    402         IF NOT EXISTS(
    403                 select 1
    404                 from blacklisted_user
    405                 where  topic_id = NEW.topic_id and user_id = NEW.user_id and end_date is NULL
    406         )
    407         THEN
    408                 RETURN NEW;
    409 END IF;
    410 RETURN NULL;
    411 END;
    412 $$;
    413 }}}
    414 
    415 {{{
    416 create or replace trigger tr_add_blacklisted_user
    417 before insert on blacklisted_user
    418 for each row
    419 execute function fn_add_blacklisted_user();
    420 }}}
    421 
    422 === Автоматско додавање на project_resource, при додавање на канал
    423 {{{
    424 create or replace function fn_add_project_resource()
    425     returns trigger
    426     language plpgsql
    427 as $$
    428 DECLARE
    429     project_resource_id INT;
    430 BEGIN
    431     insert into project_resource default values returning id into project_resource_id;
    432     new.project_resource_id := project_resource_id;
    433     return new;
    434 end;
    435 $$;
    436 }}}
    437 
    438 {{{
    439 create or replace trigger tr_add_project_resource_channel
    440     before insert
    441     on channel
    442     for each row
    443 execute function fn_add_project_resource();
    444 }}}
    445 
    446 == Индекси
    447 
    448 == Процедури
    44913[wiki:Indexes Индекси] 
    45014