| Conditions | 16 |
| Total Lines | 104 |
| Code Lines | 58 |
| Lines | 0 |
| Ratio | 0 % |
| Changes | 0 | ||
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
Complex classes like engines.*LookupEngine.LookupSubject often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
| 1 | package engines |
||
| 190 | func (engine *LookupEngine) LookupSubject(ctx context.Context, request *base.PermissionLookupSubjectRequest) (response *base.PermissionLookupSubjectResponse, err error) { |
||
| 191 | size := request.GetPageSize() |
||
| 192 | if size == 0 { |
||
| 193 | size = 1000 |
||
| 194 | } |
||
| 195 | |||
| 196 | var ids []string |
||
| 197 | var ct string |
||
| 198 | |||
| 199 | // Use the schema-based subject filter to get the list of subjects with the requested permission. |
||
| 200 | ids, err = NewSubjectFilter(engine.schemaReader, engine.dataReader, SubjectFilterConcurrencyLimit(engine.concurrencyLimit)).SubjectFilter(ctx, request) |
||
| 201 | if err != nil { |
||
| 202 | return nil, err |
||
| 203 | } |
||
| 204 | |||
| 205 | // Initialize excludedIds to be used in the query |
||
| 206 | var excludedIds []string |
||
| 207 | |||
| 208 | // Check if the wildcard '<>' is present in the ids.Ids or if it's formatted like "<>-1,2,3" |
||
| 209 | for _, id := range ids { |
||
| 210 | if id == ALL { |
||
| 211 | // Handle '<>' case: no exclusions, include all resources |
||
| 212 | excludedIds = nil |
||
| 213 | break |
||
| 214 | } else if strings.HasPrefix(id, ALL+"-") { |
||
| 215 | // Handle '<>-1,2,3' case: parse exclusions after '-' |
||
| 216 | excludedIds = strings.Split(strings.TrimPrefix(id, ALL+"-"), ",") |
||
| 217 | break |
||
| 218 | } |
||
| 219 | } |
||
| 220 | |||
| 221 | // If '<>' was found, query all subjects with exclusions if provided |
||
| 222 | if excludedIds != nil || slices.Contains(ids, ALL) { |
||
| 223 | resp, pct, err := engine.dataReader.QueryUniqueSubjectReferences( |
||
| 224 | ctx, |
||
| 225 | request.GetTenantId(), |
||
| 226 | request.GetSubjectReference(), |
||
| 227 | excludedIds, // Pass the exclusions if any |
||
| 228 | request.GetMetadata().GetSnapToken(), |
||
| 229 | database.NewPagination(database.Size(size), database.Token(request.GetContinuousToken())), |
||
| 230 | ) |
||
| 231 | if err != nil { |
||
| 232 | return nil, err |
||
| 233 | } |
||
| 234 | ct = pct.String() |
||
| 235 | |||
| 236 | // Return the list of entity IDs that have the required permission. |
||
| 237 | return &base.PermissionLookupSubjectResponse{ |
||
| 238 | SubjectIds: resp, |
||
| 239 | ContinuousToken: ct, |
||
| 240 | }, nil |
||
| 241 | } |
||
| 242 | |||
| 243 | start := "" |
||
| 244 | |||
| 245 | // Sort the IDs |
||
| 246 | sort.Strings(ids) |
||
| 247 | |||
| 248 | // Handle continuous token if present |
||
| 249 | if request.GetContinuousToken() != "" { |
||
| 250 | var t database.ContinuousToken |
||
| 251 | t, err := utils.EncodedContinuousToken{Value: request.GetContinuousToken()}.Decode() |
||
| 252 | if err != nil { |
||
| 253 | return nil, err |
||
| 254 | } |
||
| 255 | start = t.(utils.ContinuousToken).Value |
||
| 256 | } |
||
| 257 | |||
| 258 | // Since the incoming 'ids' are already filtered based on the continuous token, |
||
| 259 | // there is no need to decode or handle the continuous token manually. |
||
| 260 | // The startIndex is initialized to 0. |
||
| 261 | startIndex := 0 |
||
| 262 | |||
| 263 | if start != "" { |
||
| 264 | // Locate the position in the sorted list where the ID equals or exceeds the token value |
||
| 265 | for i, id := range ids { |
||
| 266 | if id >= start { |
||
| 267 | startIndex = i |
||
| 268 | break |
||
| 269 | } |
||
| 270 | } |
||
| 271 | } |
||
| 272 | |||
| 273 | // Convert size to int for compatibility with startIndex |
||
| 274 | pageSize := int(size) |
||
| 275 | |||
| 276 | // Calculate the end index based on the page size |
||
| 277 | end := startIndex + pageSize |
||
| 278 | if end > len(ids) { |
||
| 279 | end = len(ids) |
||
| 280 | } |
||
| 281 | |||
| 282 | // Generate the next continuous token if there are more results |
||
| 283 | if end < len(ids) { |
||
| 284 | ct = utils.NewContinuousToken(ids[end]).Encode().String() |
||
| 285 | } else { |
||
| 286 | ct = "" |
||
| 287 | } |
||
| 288 | |||
| 289 | // Return the paginated list of IDs |
||
| 290 | return &base.PermissionLookupSubjectResponse{ |
||
| 291 | SubjectIds: ids[startIndex:end], // Slice the IDs based on pagination |
||
| 292 | ContinuousToken: ct, // Return the next continuous token |
||
| 293 | }, nil |
||
| 294 | } |
||
| 322 |