Coverage for /usr/lib/python3.10/site-packages/hyd/backend/project/api/v1.py: 51%

61 statements  

« prev     ^ index     » next       coverage.py v7.0.3, created at 2023-01-05 15:47 +0000

1import shutil 

2from pathlib import Path 

3from typing import Union 

4 

5from fastapi import APIRouter, Depends, HTTPException, Security, status 

6from sqlalchemy.orm import Session 

7 

8from hyd.backend.db import get_db 

9from hyd.backend.exc import ( 

10 HTTPException_UNKNOWN_PROJECT, 

11 NameStrError, 

12 UnknownProjectError, 

13) 

14from hyd.backend.project.models import ( 

15 API_V1_CREATE__POST, 

16 API_V1_DELETE__DELETE, 

17 API_V1_GET__GET, 

18 API_V1_LIST__GET, 

19 ProjectEntry, 

20 ProjectResponseSchema, 

21) 

22from hyd.backend.project.service import ( 

23 create_project, 

24 delete_project_by_ref, 

25 read_project, 

26 read_projects, 

27) 

28from hyd.backend.security import Scopes 

29from hyd.backend.tag.models import TagEntry 

30from hyd.backend.user.authentication import authenticate_user 

31from hyd.backend.user.models import UserEntry 

32from hyd.backend.util.const import HEADERS, PATH_PROJECTS 

33from hyd.backend.util.logger import HydLogger 

34from hyd.backend.util.models import NameStr, PrimaryKey 

35from hyd.backend.version.api.v1 import version_rm_mount_and_files 

36from hyd.backend.version.models import VersionEntry 

37 

38LOGGER = HydLogger("ProjectAPI") 

39 

40v1_router = APIRouter(tags=["project"]) 

41 

42#################################################################################################### 

43#### HTTP Exceptions 

44#################################################################################################### 

45 

46HTTPException_PROJECT_NAME_NOT_AVAILABLE = HTTPException( 

47 status_code=status.HTTP_400_BAD_REQUEST, 

48 detail="Project name not available!", 

49 headers=HEADERS, 

50) 

51 

52#################################################################################################### 

53#### Scope: PROJECT 

54#################################################################################################### 

55 

56 

57@v1_router.post("/create", responses=API_V1_CREATE__POST) 

58async def _create( 

59 name: NameStr, 

60 db: Session = Depends(get_db), 

61 user_entry: UserEntry = Security(authenticate_user, scopes=[Scopes.PROJECT]), 

62): 

63 try: 

64 project_entry = create_project(name=name, db=db) 

65 except NameStrError: 

66 raise HTTPException_PROJECT_NAME_NOT_AVAILABLE 

67 

68 LOGGER.info( 

69 "{token_id: %d, user_id: %d, username: %s, project_id: %d, project_name: %s}", 

70 user_entry.session_token_entry.id, 

71 user_entry.id, 

72 user_entry.username, 

73 project_entry.id, 

74 name, 

75 ) 

76 return _project_entry_to_response_schema(project_entry) 

77 

78 

79@v1_router.get("/list", responses=API_V1_LIST__GET) 

80async def _list( 

81 db: Session = Depends(get_db), 

82 user_entry: UserEntry = Security(authenticate_user, scopes=[Scopes.PROJECT]), 

83): 

84 project_entries = read_projects(db=db) 

85 return [_project_entry_to_response_schema(project_entry) for project_entry in project_entries] 

86 

87 

88@v1_router.get("/get", responses=API_V1_GET__GET) 

89async def _get( 

90 project_id: Union[int, str], 

91 db: Session = Depends(get_db), 

92 user_entry: UserEntry = Security(authenticate_user, scopes=[Scopes.PROJECT]), 

93): 

94 user_entry.check_token_project_permission(project_id=project_id) 

95 

96 try: 

97 project_entry = read_project(project_id=project_id, db=db) 

98 except UnknownProjectError: 

99 raise HTTPException_UNKNOWN_PROJECT 

100 

101 return _project_entry_to_response_schema(project_entry) 

102 

103 

104@v1_router.delete("/delete", responses=API_V1_DELETE__DELETE) 

105async def _delete( 

106 project_id: PrimaryKey, 

107 db: Session = Depends(get_db), 

108 user_entry: UserEntry = Security(authenticate_user, scopes=[Scopes.PROJECT]), 

109): 

110 user_entry.check_token_project_permission(project_id=project_id) 

111 

112 try: 

113 project_entry = read_project(project_id=project_id, db=db) 

114 except UnknownProjectError: 

115 raise HTTPException_UNKNOWN_PROJECT 

116 

117 for version_entry in project_entry.version_entries: 

118 version_rm_mount_and_files(version_entry=version_entry, db=db) 

119 

120 shutil.rmtree(_path_to_project(project_id)) 

121 

122 LOGGER.info( 

123 "{token_id: %d, user_id: %d, username: %s, project_id: %d, project_name: %s}", 

124 user_entry.session_token_entry.id, 

125 user_entry.id, 

126 user_entry.username, 

127 project_entry.id, 

128 project_entry.name, 

129 ) 

130 

131 response = _project_entry_to_response_schema(project_entry) 

132 delete_project_by_ref(project_entry=project_entry, db=db) 

133 return response 

134 

135 

136#################################################################################################### 

137#### Util 

138#################################################################################################### 

139 

140 

141def _path_to_project(project_id: PrimaryKey) -> Path: 

142 return PATH_PROJECTS / str(project_id) 

143 

144 

145def _project_entry_to_response_schema(project_entry: ProjectEntry) -> ProjectResponseSchema: 

146 version_entries: list[VersionEntry] = project_entry.version_entries 

147 tag_entries: list[TagEntry] = project_entry.tag_entries 

148 

149 return ProjectResponseSchema( 

150 id=project_entry.id, 

151 name=project_entry.name, 

152 created_at=project_entry.created_at, 

153 versions=[version_entry.version for version_entry in version_entries], 

154 tags=[tag_entry.tag for tag_entry in tag_entries], 

155 )